| Flutter Impeller |

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

## Classes
struct | BlendModeSelection
struct | ColorBlendTestData
class | CompareFunctionUIData
struct | CVTest
struct | Foo
class | GaussianBlurFilterContentsTest
class | GoldenDigest
| Manages a global variable for tracking instances of golden images. More...
class | GoldenTests
struct | MaskBlurTestConfig
class | MetalScreenshot
| A screenshot that was produced from `MetalScreenshotter`. More...
class | MetalScreenshotter
class | RendererDartTest
struct | RWFoo
class | Screenshot
class | Screenshotter
class | TestAllocator
class | TestPassDelegate
struct | TextRenderOptions
class | VulkanScreenshotter
class | WorkingDirectory

## Typedefs
using | AiksTest = AiksPlayground
using | AiksCanvasTest = ::testing::Test
using | DisplayListTest = DlPlayground
using | EntityTest = EntityPlayground
using | HostBufferTest = EntityPlayground
using | EntityPassTargetTest = EntityPlayground
using | RenderTargetCacheTest = EntityPlayground
using | DriverInfoVKTest = PlaygroundTest
using | RendererTest = PlaygroundTest
using | BlitPassTest = PlaygroundTest
using | ComputeSubgroupTest = ComputePlaygroundTest
using | ComputeTest = ComputePlaygroundTest
using | DeviceBufferTest = Playground
using | RuntimeStageTest = RuntimeStagePlayground
using | TypographerTest = PlaygroundTest

## Functions
| TEST_P (AiksTest, CanRenderMaskBlurHugeSigma)
| TEST_P (AiksTest, CanRenderForegroundBlendWithMaskBlur)
| TEST_P (AiksTest, CanRenderForegroundAdvancedBlendWithMaskBlur)
| TEST_P (AiksTest, CanRenderBackdropBlurInteractive)
| TEST_P (AiksTest, CanRenderBackdropBlur)
| 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, BlurredRectangleWithShader)
| TEST_P (AiksTest, MaskBlurWithZeroSigmaIsSkipped)
static Picture | MaskBlurVariantTest (const AiksTest &test_context, const MaskBlurTestConfig &config)
| TEST_P (AiksTest, GaussianBlurAtPeripheryVertical)
| TEST_P (AiksTest, GaussianBlurAtPeripheryHorizontal)
| TEST_P (AiksTest, GaussianBlurWithoutDecalSupport)
| TEST_P (AiksTest, GaussianBlurOneDimension)
| TEST_P (AiksTest, GaussianBlurRotatedAndClipped)
| TEST_P (AiksTest, GaussianBlurScaledAndClipped)
| TEST_P (AiksTest, GaussianBlurRotatedAndClippedInteractive)
| TEST_P (AiksTest, GaussianBlurSolidColorTinyMipMap)
| TEST_P (AiksTest, GaussianBlurBackdropTinyMipMap)
| TEST_P (AiksTest, GaussianBlurAnimatedBackdrop)
| TEST_P (AiksTest, GaussianBlurStyleInnerGradient)
| TEST_P (AiksTest, GaussianBlurStyleSolidGradient)
| TEST_P (AiksTest, GaussianBlurStyleOuterGradient)
| TEST_P (AiksTest, GaussianBlurStyleInner)
| TEST_P (AiksTest, GaussianBlurStyleOuter)
| TEST_P (AiksTest, GaussianBlurStyleSolid)
| TEST_P (AiksTest, MaskBlurTexture)
| TEST_P (AiksTest, GuassianBlurUpdatesMipmapContents)
| TEST_P (AiksTest, GaussianBlurSetsMipCountOnPass)
| TEST_P (AiksTest, GaussianBlurAllocatesCorrectMipCountRenderTarget)
| TEST_P (AiksTest, GaussianBlurMipMapNestedLayer)
| TEST_P (AiksTest, GaussianBlurMipMapImageFilter)
| TEST_P (AiksTest, GaussianBlurMipMapSolidColor)
| TEST_P (AiksTest, MaskBlurDoesntStretchContents)
| 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, bool use_dithering)
| TEST_P (AiksTest, CanRenderLinearGradientWithDitheringDisabled)
| TEST_P (AiksTest, CanRenderLinearGradientWithDitheringEnabled)
static void | CanRenderRadialGradientWithDithering (AiksTest *aiks_test, bool use_dithering)
| TEST_P (AiksTest, CanRenderRadialGradientWithDitheringDisabled)
| TEST_P (AiksTest, CanRenderRadialGradientWithDitheringEnabled)
static void | CanRenderSweepGradientWithDithering (AiksTest *aiks_test, bool use_dithering)
| TEST_P (AiksTest, CanRenderSweepGradientWithDitheringDisabled)
| TEST_P (AiksTest, CanRenderSweepGradientWithDitheringEnabled)
static void | CanRenderConicalGradientWithDithering (AiksTest *aiks_test, bool use_dithering)
| TEST_P (AiksTest, CanRenderConicalGradientWithDitheringDisabled)
| TEST_P (AiksTest, CanRenderConicalGradientWithDitheringEnabled)
| TEST_P (AiksTest, CanRenderLinearGradientWithOverlappingStopsClamp)
| 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)
| 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 (AiksTest, GradientStrokesRenderCorrectly)
| TEST_P (AiksTest, RotateColorFilteredPath)
| TEST_P (AiksTest, CanRenderStrokes)
| TEST_P (AiksTest, CanRenderCurvedStrokes)
| TEST_P (AiksTest, CanRenderThickCurvedStrokes)
| TEST_P (AiksTest, CanRenderStrokePathThatEndsAtSharpTurn)
| TEST_P (AiksTest, CanRenderStrokePathWithCubicLine)
| TEST_P (AiksTest, CanRenderDifferencePaths)
| TEST_P (AiksTest, CanDrawAnOpenPath)
| TEST_P (AiksTest, CanDrawAnOpenPathThatIsntARect)
| TEST_P (AiksTest, SolidStrokesRenderCorrectly)
| TEST_P (AiksTest, DrawLinesRenderCorrectly)
| TEST_P (AiksTest, DrawRectStrokesRenderCorrectly)
| TEST_P (AiksTest, DrawRectStrokesWithBevelJoinRenderCorrectly)
| TEST_P (AiksTest, CanDrawMultiContourConvexPath)
| TEST_P (AiksTest, ArcWithZeroSweepAndBlur)
| TEST_P (AiksTest, CanRenderClips)
| TEST_P (AiksTest, CanRenderOverlappingMultiContourPath)
| INSTANTIATE_PLAYGROUND_SUITE (AiksTest)
| TEST_P (AiksTest, CanvasCTMCanBeUpdated)
| TEST_P (AiksTest, CanvasCanPushPopCTM)
| TEST_P (AiksTest, CanRenderColoredRect)
| TEST_P (AiksTest, CanRenderImage)
| TEST_P (AiksTest, CanRenderInvertedImageWithColorFilter)
| TEST_P (AiksTest, CanRenderColorFilterWithInvertColors)
| TEST_P (AiksTest, CanRenderColorFilterWithInvertColorsDrawPaint)
| TEST_P (AiksTest, CanRenderAdvancedBlendColorFilterWithSaveLayer)
| 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, CanRenderSimpleClips)
| TEST_P (AiksTest, CanRenderNestedClips)
| TEST_P (AiksTest, CanRenderDifferenceClips)
| TEST_P (AiksTest, CanRenderWithContiguousClipRestores)
| TEST_P (AiksTest, ClipsUseCurrentTransform)
| TEST_P (AiksTest, CanSaveLayerStandalone)
| TEST_P (AiksTest, CanRenderDifferentShapesWithSameColorSource)
| TEST_P (AiksTest, CanPictureConvertToImage)
| TEST_P (AiksTest, CanEmptyPictureConvertToImage)
| TEST_P (AiksTest, BlendModeShouldCoverWholeScreen)
| TEST_P (AiksTest, CanRenderGroupOpacity)
| TEST_P (AiksTest, CoordinateConversionsAreCorrect)
| TEST_P (AiksTest, CanPerformFullScreenMSAA)
| TEST_P (AiksTest, CanPerformSkew)
| TEST_P (AiksTest, CanPerformSaveLayerWithBounds)
| TEST_P (AiksTest, CanPerformSaveLayerWithBoundsAndLargerIntermediateIsNotAllocated)
| TEST_P (AiksTest, CanRenderRoundedRectWithNonUniformRadii)
bool | RenderTextInCanvasSkia (const std::shared_ptr< Context > &context, Canvas &canvas, const std::string &text, const std::string_view &font_fixture, TextRenderOptions options={})
bool | RenderTextInCanvasSTB (const std::shared_ptr< Context > &context, Canvas &canvas, const std::string &text, const std::string &font_fixture, TextRenderOptions options={})
| TEST_P (AiksTest, CanRenderTextFrame)
| TEST_P (AiksTest, CanRenderTextFrameSTB)
| 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, CanDrawPaint)
| TEST_P (AiksTest, CanDrawPaintMultipleTimes)
| TEST_P (AiksTest, CanDrawPaintWithAdvancedBlend)
| TEST_P (AiksTest, DrawPaintWithAdvancedBlendOverFilter)
| TEST_P (AiksTest, DrawAdvancedBlendPartlyOffscreen)
static BlendModeSelection | GetBlendModeSelection ()
| TEST_P (AiksTest, CanDrawPaintMultipleTimesInteractive)
| TEST_P (AiksTest, PaintBlendModeIsRespected)
| TEST_P (AiksTest, ColorWheel)
| TEST_P (AiksTest, TransformMultipliesCorrectly)
| TEST_P (AiksTest, FilledCirclesRenderCorrectly)
| TEST_P (AiksTest, StrokedCirclesRenderCorrectly)
| TEST_P (AiksTest, FilledEllipsesRenderCorrectly)
| TEST_P (AiksTest, FilledRoundRectsRenderCorrectly)
| TEST_P (AiksTest, SolidColorCirclesOvalsRRectsMaskBlurCorrectly)
| 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, PaintWithFilters)
| TEST_P (AiksTest, OpacityPeepHoleApplicationTest)
| TEST_P (AiksTest, DrawPaintAbsorbsClears)
| TEST_P (AiksTest, ParentSaveLayerCreatesRenderPassWhenChildBackdropFilterIsPresent)
| TEST_P (AiksTest, DrawRectAbsorbsClears)
| TEST_P (AiksTest, DrawRectAbsorbsClearsNegativeRRect)
| TEST_P (AiksTest, DrawRectAbsorbsClearsNegativeRotation)
| TEST_P (AiksTest, DrawRectAbsorbsClearsNegative)
| TEST_P (AiksTest, ClipRectElidesNoOpClips)
| TEST_P (AiksTest, ClearColorOptimizationDoesNotApplyForBackdropFilters)
| TEST_P (AiksTest, CollapsedDrawPaintInSubpass)
| TEST_P (AiksTest, CollapsedDrawPaintInSubpassBackdropFilter)
| TEST_P (AiksTest, ForegroundBlendSubpassCollapseOptimization)
| TEST_P (AiksTest, ColorMatrixFilterSubpassCollapseOptimization)
| TEST_P (AiksTest, LinearToSrgbFilterSubpassCollapseOptimization)
| TEST_P (AiksTest, SrgbToLinearFilterSubpassCollapseOptimization)
static Picture | BlendModeTest (Vector2 content_scale, BlendMode blend_mode, const std::shared_ptr< Image > &src_image, const std::shared_ptr< Image > &dst_image)
| TEST_P (AiksTest, TranslucentSaveLayerDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithBlendColorFilterDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithBlendImageFilterDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithColorAndImageFilterDrawsCorrectly)
| TEST_P (AiksTest, ImageFilteredSaveLayerWithUnboundedContents)
| 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, CanRenderOffscreenCheckerboard)
| TEST_P (AiksTest, OpaqueEntitiesGetCoercedToSource)
| TEST_P (AiksTest, CanRenderDestructiveSaveLayer)
| TEST_P (AiksTest, CanRenderClippedRuntimeEffects)
| TEST_P (AiksTest, DrawPaintTransformsBounds)
| TEST_P (AiksTest, CanDrawPoints)
| TEST_P (AiksTest, DrawAtlasWithColorAdvancedAndTransform)
| TEST_P (AiksTest, DrawAtlasAdvancedAndTransform)
| TEST_P (AiksTest, CanDrawPointsWithTextureMap)
| TEST_P (AiksTest, TextForegroundShaderWithTransform)
| TEST_P (AiksTest, MatrixSaveLayerFilter)
| TEST_P (AiksTest, MatrixBackdropFilter)
| TEST_P (AiksTest, SolidColorApplyColorFilter)
| TEST_P (AiksTest, DrawScaledTextWithPerspectiveNoSaveLayer)
| TEST_P (AiksTest, DrawScaledTextWithPerspectiveSaveLayer)
| TEST_P (AiksTest, PipelineBlendSingleParameter)
| TEST_P (AiksTest, CaptureContext)
| TEST_P (AiksTest, CaptureInactivatedByDefault)
| TEST_P (AiksTest, ReleasesTextureOnTeardown)
| TEST_P (AiksTest, VerticesGeometryUVPositionData)
| TEST_P (AiksTest, VerticesGeometryUVPositionDataWithTranslate)
| TEST_P (AiksTest, ClearBlend)
| TEST_P (AiksTest, MatrixImageFilterMagnify)
| TEST_P (AiksTest, MatrixImageFilterDoesntCullWhenTranslatedFromOffscreen)
| TEST_P (AiksTest, MatrixImageFilterDoesntCullWhenScaledAndTranslatedFromOffscreen)
| TEST_P (AiksTest, ClearColorOptimizationWhenSubpassIsBiggerThanParentPass)
| TEST_P (AiksTest, EmptySaveLayerIgnoresPaint)
| TEST_P (AiksTest, EmptySaveLayerRendersWithClear)
| TEST_P (AiksTest, SubpassWithClearColorOptimization)
| TEST_P (AiksTest, ImageColorSourceEffectTransform)
| TEST_P (AiksTest, CorrectClipDepthAssignedToEntities)
| TEST_P (AiksTest, CanDrawPerspectiveTransformWithClips)
| TEST_P (AiksTest, CanRenderClippedBackdropFilter)
| TEST (CanvasRecorder, Save)
| TEST (CanvasRecorder, SaveLayer)
| TEST (CanvasRecorder, Restore)
| TEST (CanvasRecorder, RestoreToCount)
| TEST (CanvasRecorder, ResetTransform)
| TEST (CanvasRecorder, Transform)
| TEST (CanvasRecorder, Concat)
| TEST (CanvasRecorder, PreConcat)
| TEST (CanvasRecorder, Translate)
| TEST (CanvasRecorder, Scale2)
| TEST (CanvasRecorder, Scale3)
| TEST (CanvasRecorder, Skew)
| TEST (CanvasRecorder, Rotate)
| TEST (CanvasRecorder, DrawPath)
| TEST (CanvasRecorder, DrawPaint)
| TEST (CanvasRecorder, DrawLine)
| TEST (CanvasRecorder, DrawRect)
| TEST (CanvasRecorder, DrawOval)
| TEST (CanvasRecorder, DrawRRect)
| TEST (CanvasRecorder, DrawCircle)
| TEST (CanvasRecorder, DrawPoints)
| TEST (CanvasRecorder, DrawImage)
| TEST (CanvasRecorder, DrawImageRect)
| TEST (CanvasRecorder, ClipPath)
| TEST (CanvasRecorder, ClipRect)
| TEST (CanvasRecorder, ClipOval)
| TEST (CanvasRecorder, ClipRRect)
| TEST (CanvasRecorder, DrawTextFrame)
| TEST (CanvasRecorder, DrawVertices)
| TEST (CanvasRecorder, DrawAtlas)
| TEST (AiksCanvasTest, EmptyCullRect)
| TEST (AiksCanvasTest, InitialCullRect)
| TEST (AiksCanvasTest, TranslatedCullRect)
| TEST (AiksCanvasTest, ScaledCullRect)
| TEST (AiksCanvasTest, RectClipIntersectAgainstEmptyCullRect)
| TEST (AiksCanvasTest, RectClipDiffAgainstEmptyCullRect)
| TEST (AiksCanvasTest, RectClipIntersectAgainstCullRect)
| TEST (AiksCanvasTest, RectClipDiffAgainstNonCoveredCullRect)
| TEST (AiksCanvasTest, RectClipDiffAboveCullRect)
| TEST (AiksCanvasTest, RectClipDiffBelowCullRect)
| TEST (AiksCanvasTest, RectClipDiffLeftOfCullRect)
| TEST (AiksCanvasTest, RectClipDiffRightOfCullRect)
| TEST (AiksCanvasTest, RectClipDiffAgainstVCoveredCullRect)
| TEST (AiksCanvasTest, RectClipDiffAgainstHCoveredCullRect)
| TEST (AiksCanvasTest, RRectClipIntersectAgainstEmptyCullRect)
| TEST (AiksCanvasTest, RRectClipDiffAgainstEmptyCullRect)
| TEST (AiksCanvasTest, RRectClipIntersectAgainstCullRect)
| TEST (AiksCanvasTest, RRectClipDiffAgainstNonCoveredCullRect)
| TEST (AiksCanvasTest, RRectClipDiffAgainstVPartiallyCoveredCullRect)
| TEST (AiksCanvasTest, RRectClipDiffAgainstVFullyCoveredCullRect)
| TEST (AiksCanvasTest, RRectClipDiffAgainstHPartiallyCoveredCullRect)
| TEST (AiksCanvasTest, RRectClipDiffAgainstHFullyCoveredCullRect)
| TEST (AiksCanvasTest, PathClipIntersectAgainstEmptyCullRect)
| TEST (AiksCanvasTest, PathClipDiffAgainstEmptyCullRect)
| TEST (AiksCanvasTest, PathClipIntersectAgainstCullRect)
| TEST (AiksCanvasTest, PathClipDiffAgainstNonCoveredCullRect)
| TEST (AiksCanvasTest, PathClipDiffAgainstFullyCoveredCullRect)
| TEST (AiksCanvasTest, DisableLocalBoundsRectForFilteredSaveLayers)
| TEST (TraceSerializer, Save)
| 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)
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, DispatcherDoesNotCullPerspectiveTransformedChildDisplayLists)
| TEST_P (DisplayListTest, TransparentShadowProducesCorrectColor)
| TEST_P (DisplayListTest, CanConvertTriangleFanToTriangles)
| 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, DrawVerticesSolidColorTrianglesWithoutIndices)
| TEST_P (DisplayListTest, DrawVerticesLinearGradientWithoutIndices)
| TEST_P (DisplayListTest, DrawVerticesLinearGradientWithTextureCoordinates)
| TEST_P (DisplayListTest, DrawVerticesImageSourceWithTextureCoordinates)
| TEST_P (DisplayListTest, DrawVerticesImageSourceWithTextureCoordinatesAndColorBlending)
| TEST_P (DisplayListTest, DrawVerticesSolidColorTrianglesWithIndices)
| TEST_P (DisplayListTest, DrawVerticesPremultipliesColors)
| TEST_P (DisplayListTest, DrawShapes)
| TEST_P (DisplayListTest, ClipDrawRRectWithNonCircularRadii)
| TEST_P (DisplayListTest, DrawVerticesBlendModes)
template<typename Contents >
static std::optional< Rect > | GetCoverageOfFirstEntity (const Picture &picture)
| TEST (DisplayListTest, RRectBoundsComputation)
| TEST (DisplayListTest, CircleBoundsComputation)
| TEST_P (DisplayListTest, DrawPaintIgnoresMaskFilter)
| TEST (SkiaConversionsTest, SkPointToPoint)
| TEST (SkiaConversionsTest, SkPointToSize)
| TEST (SkiaConversionsTest, ToColor)
| TEST (SkiaConversionsTest, GradientStopConversion)
| TEST (SkiaConversionsTest, GradientMissing0)
| TEST (SkiaConversionsTest, GradientMissingLastValue)
| TEST (SkiaConversionsTest, GradientStopGreaterThan1)
| TEST (SkiaConversionsTest, GradientConversionNonMonotonic)
| TEST (ContentContext, CachesPipelines)
| TEST (ContentContext, InvalidatesAllPipelinesWithSameUniqueNameOnClear)
| TEST (ContentContext, InitializeCommonlyUsedShadersIfNeeded)
| 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 (FilterInputTest, CanSetLocalTransformForTexture)
| TEST (FilterInputTest, IsLeaf)
| TEST (FilterInputTest, SetCoverageInputs)
| INSTANTIATE_PLAYGROUND_SUITE (HostBufferTest)
| 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 (EntityTest, TiledTextureContentsRendersWithCorrectPipeline)
| TEST_P (EntityTest, TiledTextureContentsRendersWithCorrectPipelineExternalOES)
std::shared_ptr< VerticesGeometry > | CreateColorVertices (const std::vector< Point > &vertices, const std::vector< Color > &colors)
| TEST_P (EntityTest, RendersDstPerColorWithAlpha)
| TEST_P (EntityPassTargetTest, SwapWithMSAATexture)
| TEST_P (EntityPassTargetTest, SwapWithMSAAImplicitResolve)
| TEST (EntityPassClipStackTest, CanPushAndPopEntities)
| TEST (EntityPassClipStackTest, CanPopEntitiesSafely)
| TEST (EntityPassClipStackTest, CanAppendNoChange)
| TEST (EntityPassClipStackTest, AppendCoverageNoChange)
| TEST (EntityPassClipStackTest, AppendAndRestoreClipCoverage)
| TEST (EntityPassClipStackTest, UnbalancedRestore)
| TEST (EntityPassClipStackTest, ClipAndRestoreWithSubpasses)
| TEST_P (EntityTest, CanCreateEntity)
auto | CreatePassWithRectPath (Rect rect, std::optional< Rect > bounds_hint, ContentBoundsPromise bounds_promise=ContentBoundsPromise::kUnknown, bool collapse=false)
| TEST_P (EntityTest, EntityPassRespectsUntrustedSubpassBoundsLimit)
| TEST_P (EntityTest, EntityPassTrustsSnugSubpassBoundsLimit)
| TEST_P (EntityTest, EntityPassCanMergeSubpassIntoParent)
| TEST_P (EntityTest, EntityPassCoverageRespectsCoverageLimit)
| TEST_P (EntityTest, FilterCoverageRespectsCropRect)
| TEST_P (EntityTest, CanDrawRect)
| TEST_P (EntityTest, CanDrawRRect)
| 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, DrawAtlasNoColor)
| TEST_P (EntityTest, DrawAtlasWithColorAdvanced)
| TEST_P (EntityTest, DrawAtlasWithColorSimple)
| TEST_P (EntityTest, DrawAtlasUsesProvidedCullRectForCoverage)
| TEST_P (EntityTest, DrawAtlasWithOpacity)
| TEST_P (EntityTest, DrawAtlasNoColorFullSize)
| TEST_P (EntityTest, SolidFillCoverageIsCorrect)
| TEST_P (EntityTest, SolidFillShouldRenderIsCorrect)
| TEST_P (EntityTest, DoesNotCullEntitiesByDefault)
| TEST_P (EntityTest, ClipContentsShouldRenderIsCorrect)
| TEST_P (EntityTest, ClipContentsGetClipCoverageIsCorrect)
| 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)
| TEST_P (EntityTest, AtlasContentsSubAtlas)
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, RuntimeEffectSetsRightSizeWhenUniformIsStruct)
| TEST_P (EntityTest, InheritOpacityTest)
| 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, PointFieldGeometryDivisions)
| TEST_P (EntityTest, PointFieldGeometryCoverage)
| TEST_P (EntityTest, ColorFilterContentsWithLargeGeometry)
| TEST_P (EntityTest, TextContentsCeilsGlyphScaleToDecimal)
| TEST_P (EntityTest, AdvancedBlendCoverageHintIsNotResetByEntityPass)
| 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 (EntityGeometryTest, RectGeometryCoversArea)
| TEST (EntityGeometryTest, FillPathGeometryCoversArea)
| TEST (EntityGeometryTest, FillPathGeometryCoversAreaNoInnerRect)
| TEST (EntityGeometryTest, LineGeometryCoverage)
| TEST (EntityGeometryTest, RoundRectGeometryCoversArea)
| TEST (EntityGeometryTest, StrokePathGeometryTransformOfLine)
| TEST (EntityGeometryTest, GeometryResultHasReasonableDefaults)
| TEST_P (RenderTargetCacheTest, CachesUsedTexturesAcrossFrames)
| TEST_P (RenderTargetCacheTest, DoesNotPersistFailedAllocations)
| TEST_P (RenderTargetCacheTest, CachedTextureGetsNewAttachmentConfig)
| TEST_P (RenderTargetCacheTest, CreateWithEmptySize)
| 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, MatrixGetMaxBasisLength)
| TEST (GeometryTest, MatrixGetMaxBasisLengthXY)
| TEST (GeometryTest, MatrixMakeOrthographic)
| TEST (GeometryTest, MatrixMakePerspective)
| TEST (GeometryTest, MatrixGetBasisVectors)
| TEST (GeometryTest, MatrixGetDirectionScale)
| TEST (GeometryTest, MatrixIsAligned)
| 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, PointAngleTo)
| TEST (GeometryTest, PointMin)
| 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, 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 (PathTest, CubicPathComponentPolylineDoesNotIncludePointOne)
| TEST (PathTest, PathCreatePolyLineDoesNotDuplicatePoints)
| 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, CubicPath)
| TEST (PathTest, BoundingBoxCubic)
| TEST (PathTest, BoundingBoxOfCompositePathIsCorrect)
| TEST (PathTest, ExtremaOfCubicPathComponentIsCorrect)
| TEST (PathTest, PathGetBoundingBoxForCubicWithNoDerivativeRootsIsCorrect)
| TEST (PathTest, EmptyPath)
| TEST (PathTest, SimplePath)
| TEST (PathTest, CanBeCloned)
| 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, 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, 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 (SaturatedMath, ExplicitAddOfSignedInts)
| TEST (SaturatedMath, ImplicitAddOfSignedInts)
| TEST (SaturatedMath, ExplicitAddOfFloatingPoint)
| TEST (SaturatedMath, ImplicitAddOfFloatingPoint)
| TEST (SaturatedMath, ExplicitSubOfSignedInts)
| TEST (SaturatedMath, ImplicitSubOfSignedInts)
| TEST (SaturatedMath, ExplicitSubOfFloatingPoint)
| TEST (SaturatedMath, ImplicitSubOfFloatingPoint)
| TEST (SaturatedMath, ExplicitAverageScalarOfSignedInts)
| TEST (SaturatedMath, ImplicitAverageScalarOfSignedInts)
| TEST (SaturatedMath, ExplicitAverageScalarOfFloatingPoint)
| TEST (SaturatedMath, ImplicitAverageScalarOfFloatingPoint)
| TEST (SaturatedMath, CastingFiniteDoubleToFloatStaysFinite)
| TEST (SaturatedMath, CastingInfiniteDoubleToFloatStaysInfinite)
| TEST (SaturatedMath, CastingNaNDoubleToFloatStaysNaN)
| TEST (SaturatedMath, CastingLargeScalarToSignedIntProducesLimit)
| TEST (SaturatedMath, CastingInfiniteScalarToSignedIntProducesLimit)
| TEST (SaturatedMath, CastingNaNScalarToSignedIntProducesZero)
| TEST (SizeTest, SizeIsEmpty)
| TEST (SizeTest, ISizeIsEmpty)
| TEST (SizeTest, IsSquare)
| TEST (SizeTest, MaxDimension)
| TEST (SizeTest, NegationOperator)
| TEST (TrigTest, TrigAngles)
| TEST (TrigTest, MultiplyByScalarRadius)
| TEST_F (GoldenTests, ConicalGradient)
| TEST (TextureMTL, CreateFromDrawable)
| TEST (AllocatorVKTest, ToVKImageUsageFlags)
| TEST (AllocatorVKTest, MemoryTypeSelectionSingleHeap)
| TEST (AllocatorVKTest, MemoryTypeSelectionTwoHeap)
| TEST (BlitCommandVkTest, BlitCopyTextureToTextureCommandVK)
| TEST (BlitCommandVkTest, BlitCopyTextureToBufferCommandVK)
| TEST (BlitCommandVkTest, BlitCopyBufferToTextureCommandVK)
| TEST (BlitCommandVkTest, BlitGenerateMipmapCommandVK)
| TEST (CommandEncoderVKTest, DeleteEncoderAfterThreadDies)
| TEST (CommandEncoderVKTest, CleanupAfterSubmit)
| TEST (CommandPoolRecyclerVKTest, GetsACommandPoolPerThread)
| TEST (CommandPoolRecyclerVKTest, GetsTheSameCommandPoolOnSameThread)
| TEST (CommandPoolRecyclerVKTest, ReclaimMakesCommandPoolAvailable)
| TEST (CommandPoolRecyclerVKTest, CommandBuffersAreRecycled)
| TEST (ContextVKTest, CommonHardwareConcurrencyConfigurations)
| TEST (ContextVKTest, DeletesCommandPools)
| TEST (ContextVKTest, DeletesCommandPoolsOnAllThreads)
| 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 (DescriptorPoolRecyclerVKTest, GetDescriptorPoolRecyclerCreatesNewPools)
| TEST (DescriptorPoolRecyclerVKTest, ReclaimMakesDescriptorPoolAvailable)
| TEST (DescriptorPoolRecyclerVKTest, ReclaimDropsDescriptorPoolIfSizeIsExceeded)
| INSTANTIATE_VULKAN_PLAYGROUND_SUITE (DriverInfoVKTest)
| TEST_P (DriverInfoVKTest, CanQueryDriverInfo)
| TEST (FenceWaiterVKTest, IgnoresNullFence)
| TEST (FenceWaiterVKTest, IgnoresNullCallback)
| TEST (FenceWaiterVKTest, ExecutesFenceCallback)
| TEST (FenceWaiterVKTest, ExecutesFenceCallbackX2)
| TEST (FenceWaiterVKTest, ExecutesNewFenceThenOldFence)
| TEST (FenceWaiterVKTest, AddFenceDoesNothingIfTerminating)
| TEST (FenceWaiterVKTest, InProgressFencesStillWaitIfTerminated)
| TEST (RenderPassBuilder, CreatesRenderPassWithNoDepthStencil)
| TEST (RenderPassBuilder, CreatesRenderPassWithCombinedDepthStencil)
| TEST (RenderPassBuilder, CreatesRenderPassWithOnlyStencil)
| TEST (RenderPassBuilder, CreatesMSAAResolveWithCorrectStore)
| TEST_P (RendererTest, CachesRenderPassAndFramebuffer)
| TEST (ResourceManagerVKTest, CreatesANewInstance)
| TEST (ResourceManagerVKTest, ReclaimMovesAResourceAndDestroysIt)
| TEST (ResourceManagerVKTest, TerminatesWhenOutOfScope)
| TEST (ResourceManagerVKTest, IsThreadSafe)
| INSTANTIATE_PLAYGROUND_SUITE (BlitPassTest)
| TEST_P (BlitPassTest, BlitAcrossDifferentPixelFormatsFails)
| TEST_P (BlitPassTest, BlitAcrossDifferentSampleCountsFails)
| TEST_P (BlitPassTest, BlitPassesForMatchingFormats)
| CAPABILITY_TEST (SupportsOffscreenMSAA, false)
| CAPABILITY_TEST (SupportsSSBO, false)
| CAPABILITY_TEST (SupportsBufferToTextureBlits, 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)
| TEST (CapabilitiesTest, DefaultColorFormat)
| TEST (CapabilitiesTest, DefaultStencilFormat)
| TEST (CapabilitiesTest, DefaultDepthStencilFormat)
| TEST (CapabilitiesTest, DefaultGlyphAtlasFormat)
| INSTANTIATE_COMPUTE_SUITE (ComputeSubgroupTest)
| TEST_P (ComputeSubgroupTest, CapabilitiesSuportSubgroups)
| TEST_P (ComputeSubgroupTest, PathPlayground)
| TEST_P (ComputeSubgroupTest, LargePath)
| TEST_P (ComputeSubgroupTest, QuadAndCubicInOnePath)
| 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)
| DART_TEST_CASE (canCreateShaderLibrary)
| DART_TEST_CASE (canReflectUniformStructs)
| DART_TEST_CASE (uniformBindFailsForInvalidHostBufferOffset)
| DART_TEST_CASE (canCreateRenderPassAndSubmit)
| TEST_P (RendererTest, CanCreateBoxPrimitive)
| 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, ArrayUniforms)
| TEST_P (RendererTest, InactiveUniforms)
| TEST_P (RendererTest, CanCreateCPUBackedTexture)
| 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)
| INSTANTIATE_PLAYGROUND_SUITE (RuntimeStageTest)
| TEST_P (RuntimeStageTest, CanReadValidBlob)
| TEST_P (RuntimeStageTest, CanRejectInvalidBlob)
| TEST_P (RuntimeStageTest, CanReadUniforms)
| TEST_P (RuntimeStageTest, CanRegisterStage)
| TEST_P (RuntimeStageTest, CanCreatePipelineFromRuntimeStage)
| TEST_P (RuntimeStageTest, ContainsExpectedShaderTypes)
static std::shared_ptr< fml::Mapping > | CreateMappingFromString (std::string p_string)
const std::string | CreateStringFromMapping (const fml::Mapping &mapping)
| TEST (ShaderArchiveTest, CanReadAndWriteBlobs)
| TEST (ShaderArchiveTest, ArchiveAndMultiArchiveHaveDifferentIdentifiers)
| TEST (TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus)
| TEST (TessellatorTest, TessellateConvex)
| 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, GlyphAtlas::Type type, Scalar scale, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const TextFrame &frame)
| 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, GlyphAtlasTextureIsRecreatedIfTypeChanges)
| TEST_P (TypographerTest, MaybeHasOverlapping)
| TEST_P (TypographerTest, RectanglePackerAddsNonoverlapingRectangles)
| TEST_P (TypographerTest, GlyphAtlasTextureIsRecycledWhenContentsAreNotRecreated)

## Variables
static const std::map< std::string, MaskBlurTestConfig > | kPaintVariations
static constexpr std::string_view | kFontFixture
std::vector< Point > | golden_cubic_and_quad_points

## Typedef Documentation

## ◆ AiksCanvasTest

using impeller::testing::AiksCanvasTest = typedef ::testing::Test

Definition at line 16 of file canvas_unittests.cc.

## ◆ AiksTest

using impeller::testing::AiksTest = typedef AiksPlayground

Definition at line 17 of file aiks_unittests.h.

## ◆ BlitPassTest

using impeller::testing::BlitPassTest = typedef PlaygroundTest

Definition at line 15 of file blit_pass_unittests.cc.

## ◆ ComputeSubgroupTest

using impeller::testing::ComputeSubgroupTest = typedef ComputePlaygroundTest

Definition at line 39 of file compute_subgroup_unittests.cc.

## ◆ ComputeTest

using impeller::testing::ComputeTest = typedef ComputePlaygroundTest

Definition at line 21 of file compute_unittests.cc.

## ◆ 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 46 of file dl_unittests.cc.

## ◆ DriverInfoVKTest

using impeller::testing::DriverInfoVKTest = typedef PlaygroundTest

Definition at line 11 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 20 of file checkerboard_contents_unittests.cc.

## ◆ HostBufferTest

using impeller::testing::HostBufferTest = typedef EntityPlayground

Definition at line 12 of file host_buffer_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 19 of file render_target_cache_unittests.cc.

## ◆ RuntimeStageTest

using impeller::testing::RuntimeStageTest = typedef RuntimeStagePlayground

Definition at line 25 of file runtime_stage_unittests.cc.

## ◆ TypographerTest

using impeller::testing::TypographerTest = typedef PlaygroundTest

Definition at line 25 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 Picture impeller::testing::BlendModeTest | ( | Vector2 | content_scale,
|  | BlendMode | blend_mode,
|  | const std::shared_ptr< Image > & | src_image,
|  | const std::shared_ptr< Image > & | dst_image
| ) |  |
| 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 2233 of file aiks_unittests.cc.

2236 {
2237 Color destination_color = Color::CornflowerBlue().WithAlpha(0.75);
2238 auto source_colors = std::vector<Color>({Color::White().WithAlpha(0.75),
2239 Color::LimeGreen().WithAlpha(0.75),
2240 Color::Black().WithAlpha(0.75)});
2241
2242 Canvas canvas;
2243 canvas.DrawPaint({.color = Color::Black()});
2244 // TODO(bdero): Why does this cause the left image to double scale on high DPI
2245 // displays.
2246 // canvas.Scale(content_scale);
2247
2248 //----------------------------------------------------------------------------
2249 /// 1. Save layer blending (top squares).
2250 ///
2251
2252 canvas.Save();
2253 for (const auto& color : source_colors) {
2254 canvas.Save();
2255 {
2256 canvas.ClipRect(Rect::MakeXYWH(25, 25, 100, 100));
2257 // Perform the blend in a SaveLayer so that the initial backdrop color is
2258 // fully transparent black. SourceOver blend the result onto the parent
2259 // pass.
2260 canvas.SaveLayer({});
2261 {
2262 canvas.DrawPaint({.color = destination_color});
2263 // Draw the source color in an offscreen pass and blend it to the parent
2264 // pass.
2265 canvas.SaveLayer({.blend_mode = blend_mode});
2266 { //
2267 canvas.DrawRect(Rect::MakeXYWH(25, 25, 100, 100), {.color = color});
2268 }
2269 canvas.Restore();
2270 }
2271 canvas.Restore();
2272 }
2273 canvas.Restore();
2274 canvas.Translate(Vector2(100, 0));
2275 }
2276 canvas.RestoreToCount(0);
2277
2278 //----------------------------------------------------------------------------
2279 /// 2. CPU blend modes (bottom squares).
2280 ///
2281
2282 canvas.Save();
2283 canvas.Translate({0, 100});
2284 // Perform the blend in a SaveLayer so that the initial backdrop color is
2285 // fully transparent black. SourceOver blend the result onto the parent pass.
2286 canvas.SaveLayer({});
2287 for (const auto& color : source_colors) {
2288 // Simply write the CPU blended color to the pass.
2289 canvas.DrawRect(Rect::MakeXYWH(25, 25, 100, 100),
2290 {.color = destination_color.Blend(color, blend_mode),
2291 .blend_mode = BlendMode::kSourceOver});
2292 canvas.Translate(Vector2(100, 0));
2293 }
2294 canvas.Restore();
2295 canvas.Restore();
2296
2297 //----------------------------------------------------------------------------
2298 /// 3. Image blending (bottom images).
2299 ///
2300 /// Compare these results with the images in the Flutter blend mode
2301 /// documentation: https://api.flutter.dev/flutter/dart-ui/BlendMode.html
2302 ///
2303
2304 canvas.Translate({0, 250});
2305
2306 // Draw grid behind the images.
2307 canvas.DrawRect(Rect::MakeLTRB(0, 0, 800, 400),
2308 {.color = Color::MakeRGBA8(41, 41, 41, 255)});
2309 Paint square_paint = {.color = Color::MakeRGBA8(15, 15, 15, 255)};
2310 for (int y = 0; y < 400 / 8; y++) {
2311 for (int x = 0; x < 800 / 16; x++) {
2312 canvas.DrawRect(Rect::MakeXYWH(x * 16 + (y % 2) * 8, y * 8, 8, 8),
2313 square_paint);
2314 }
2315 }
2316
2317 // Uploaded image source (left image).
2318 canvas.Save();
2319 canvas.SaveLayer({.blend_mode = BlendMode::kSourceOver});
2320 {
2321 canvas.DrawImage(dst_image, {0, 0}, {.blend_mode = BlendMode::kSourceOver});
2322 canvas.DrawImage(src_image, {0, 0}, {.blend_mode = blend_mode});
2323 }
2324 canvas.Restore();
2325 canvas.Restore();
2326
2327 // Rendered image source (right image).
2328 canvas.Save();
2329 canvas.SaveLayer({.blend_mode = BlendMode::kSourceOver});
2330 {
2331 canvas.DrawImage(dst_image, {400, 0},
2332 {.blend_mode = BlendMode::kSourceOver});
2333 canvas.SaveLayer({.blend_mode = blend_mode});
2334 {
2335 canvas.DrawImage(src_image, {400, 0},
2336 {.blend_mode = BlendMode::kSourceOver});
2337 }
2338 canvas.Restore();
2339 }
2340 canvas.Restore();
2341 canvas.Restore();
2342
2343 return canvas.EndRecordingAsPicture();
2344 }

References impeller::Color::Black(), impeller::Color::Blend(), impeller::Paint::color, impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::kSourceOver, impeller::Color::LimeGreen(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Color::MakeRGBA8(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ CanRenderConicalGradientWithDithering()

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

Definition at line 166 of file aiks_gradient_unittests.cc.

167 {
168 Canvas canvas;
169 canvas.Scale(aiks_test->GetContentScale());
170 Paint paint;
171 canvas.Translate({100.0, 100.0, 0});
172
173 // #FFF -> #000
174 std::vector<Color> colors = {Color{1.0, 1.0, 1.0, 1.0},
175 Color{0.0, 0.0, 0.0, 1.0}};
176 std::vector<Scalar> stops = {0.0, 1.0};
177
178 paint.color_source = ColorSource::MakeConicalGradient(
179 {100, 100}, 100, std::move(colors), std::move(stops), {0, 1}, 0,
180 Entity::TileMode::kMirror, {});
181 paint.dither = use_dithering;
182
183 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
184 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
185 }

References impeller::Paint::color_source, impeller::Paint::dither, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Playground::GetContentScale(), impeller::Entity::kMirror, impeller::ColorSource::MakeConicalGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::AiksPlayground::OpenPlaygroundHere(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

Referenced by TEST_P().

## ◆ CanRenderLinearGradientWithDithering()

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

Definition at line 82 of file aiks_gradient_unittests.cc.

83 {
84 Canvas canvas;
85 Paint paint;
86 canvas.Translate({100.0, 100.0, 0});
87
88 // 0xffcccccc --> 0xff333333, taken from
89 // https://github.com/flutter/flutter/issues/118073#issue-1521699748
90 std::vector<Color> colors = {Color{0.8, 0.8, 0.8, 1.0},
91 Color{0.2, 0.2, 0.2, 1.0}};
92 std::vector<Scalar> stops = {0.0, 1.0};
93
94 paint.color_source = ColorSource::MakeLinearGradient(
95 {0, 0}, {800, 500}, std::move(colors), std::move(stops),
96 Entity::TileMode::kClamp, {});
97 paint.dither = use_dithering;
98 canvas.DrawRect(Rect::MakeXYWH(0, 0, 800, 500), paint);
99 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
100 }

References impeller::Paint::color_source, impeller::Paint::dither, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::AiksPlayground::OpenPlaygroundHere(), and impeller::Canvas::Translate().

Referenced by TEST_P().

## ◆ CanRenderRadialGradientWithDithering()

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

Definition at line 110 of file aiks_gradient_unittests.cc.

111 {
112 Canvas canvas;
113 Paint paint;
114 canvas.Translate({100.0, 100.0, 0});
115
116 // #FFF -> #000
117 std::vector<Color> colors = {Color{1.0, 1.0, 1.0, 1.0},
118 Color{0.0, 0.0, 0.0, 1.0}};
119 std::vector<Scalar> stops = {0.0, 1.0};
120
121 paint.color_source = ColorSource::MakeRadialGradient(
122 {600, 600}, 600, std::move(colors), std::move(stops),
123 Entity::TileMode::kClamp, {});
124 paint.dither = use_dithering;
125 canvas.DrawRect(Rect::MakeXYWH(0, 0, 1200, 1200), paint);
126 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
127 }

References impeller::Paint::color_source, impeller::Paint::dither, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::ColorSource::MakeRadialGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::AiksPlayground::OpenPlaygroundHere(), and impeller::Canvas::Translate().

Referenced by TEST_P().

## ◆ CanRenderSweepGradientWithDithering()

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

Definition at line 137 of file aiks_gradient_unittests.cc.

138 {
139 Canvas canvas;
140 canvas.Scale(aiks_test->GetContentScale());
141 Paint paint;
142 canvas.Translate({100.0, 100.0, 0});
143
144 // #FFF -> #000
145 std::vector<Color> colors = {Color{1.0, 1.0, 1.0, 1.0},
146 Color{0.0, 0.0, 0.0, 1.0}};
147 std::vector<Scalar> stops = {0.0, 1.0};
148
149 paint.color_source = ColorSource::MakeSweepGradient(
150 {100, 100}, Degrees(45), Degrees(135), std::move(colors),
151 std::move(stops), Entity::TileMode::kMirror, {});
152 paint.dither = use_dithering;
153
154 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
155 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
156 }

References impeller::Paint::color_source, impeller::Paint::dither, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Playground::GetContentScale(), impeller::Entity::kMirror, impeller::ColorSource::MakeSweepGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::AiksPlayground::OpenPlaygroundHere(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

Referenced by TEST_P().

## ◆ CAPABILITY_TEST() [1/10]

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

## ◆ CAPABILITY_TEST() [2/10]

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

## ◆ CAPABILITY_TEST() [3/10]

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

## ◆ CAPABILITY_TEST() [4/10]

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

## ◆ CAPABILITY_TEST() [5/10]

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

## ◆ CAPABILITY_TEST() [6/10]

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

## ◆ CAPABILITY_TEST() [7/10]

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

## ◆ CAPABILITY_TEST() [8/10]

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

## ◆ CAPABILITY_TEST() [9/10]

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

## ◆ CAPABILITY_TEST() [10/10]

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

## ◆ CompareFunctionUI()

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

Definition at line 1111 of file renderer_unittests.cc.

1111 {
1112 static CompareFunctionUIData data;
1113 return data;
1114 }

Referenced by TEST_P().

## ◆ CreateColorVertices()

std::shared_ptr<VerticesGeometry> impeller::testing::CreateColorVertices | ( | const std::vector< Point > & | vertices,
|  | const std::vector< Color > & | colors
| ) |  |

Definition at line 26 of file vertices_contents_unittests.cc.

28 {
29 auto bounds = Rect::MakePointBounds(vertices.begin(), vertices.end());
30 std::vector<uint16_t> indices = {};
31 indices.reserve(vertices.size());
32 for (auto i = 0u; i < vertices.size(); i++) {
33 indices.emplace_back(i);
34 }
35 std::vector<Point> texture_coordinates = {};
36
37 return std::make_shared<VerticesGeometry>(
38 vertices, indices, texture_coordinates, colors,
39 bounds.value_or(Rect::MakeLTRB(0, 0, 0, 0)),
40 VerticesGeometry::VertexMode::kTriangles);
41 }

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

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

1304 {
1305 using TexturePipelineBuilder = PipelineBuilder<VertexShader, FragmentShader>;
1306 auto pipeline_desc =
1307 TexturePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1308 if (!pipeline_desc.has_value()) {
1309 return nullptr;
1310 }
1311 pipeline_desc->SetSampleCount(SampleCount::kCount4);
1312 pipeline_desc->SetStencilAttachmentDescriptors(std::nullopt);
1313 auto pipeline =
1314 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
1315 if (!pipeline || !pipeline->IsValid()) {
1316 return nullptr;
1317 }
1318 return pipeline;
1319 }

References impeller::kCount4.

## ◆ CreateGlyphAtlas()

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

Definition at line 28 of file typographer_unittests.cc.

34 {
35 FontGlyphMap font_glyph_map;
36 frame.CollectUniqueFontGlyphPairs(font_glyph_map, scale);
37 return typographer_context->CreateGlyphAtlas(context, type, atlas_context,
38 font_glyph_map);
39 }

References impeller::TextFrame::CollectUniqueFontGlyphPairs(), impeller::TypographerContext::CreateGlyphAtlas(), and scale.

Referenced by TEST_P().

## ◆ CreateMappingFromString()

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

Definition at line 20 of file shader_archive_unittests.cc.

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

Referenced by TEST().

## ◆ CreatePassWithRectPath()

auto impeller::testing::CreatePassWithRectPath | ( | Rect | rect,
|  | std::optional< Rect > | bounds_hint,
|  | ContentBoundsPromise | bounds_promise = `ContentBoundsPromise::kUnknown`,
|  | bool | collapse = `false`
| ) |  |

Definition at line 109 of file entity_unittests.cc.

113 {
114 auto subpass = std::make_unique<EntityPass>();
115 Entity entity;
116 entity.SetContents(SolidColorContents::Make(
117 PathBuilder{}.AddRect(rect).TakePath(), Color::Red()));
118 subpass->AddEntity(std::move(entity));
119 subpass->SetDelegate(std::make_unique<TestPassDelegate>(collapse));
120 subpass->SetBoundsLimit(bounds_hint, bounds_promise);
121 return subpass;
122 }

References impeller::PathBuilder::AddRect(), impeller::SolidColorContents::Make(), impeller::Color::Red(), and impeller::Entity::SetContents().

Referenced by TEST_P().

## ◆ CreateStringFromMapping()

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

Definition at line 28 of file shader_archive_unittests.cc.

28 {
29 return std::string{reinterpret_cast<const char*>(mapping.GetMapping()),
30 mapping.GetSize()};
31 }

Referenced by TEST().

## ◆ CreateTestYUVTextures()

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

Definition at line 2110 of file entity_unittests.cc.

2112 {
2113 Vector3 red = {244.0 / 255.0, 67.0 / 255.0, 54.0 / 255.0};
2114 Vector3 green = {76.0 / 255.0, 175.0 / 255.0, 80.0 / 255.0};
2115 Vector3 blue = {33.0 / 255.0, 150.0 / 255.0, 243.0 / 255.0};
2116 Vector3 white = {1.0, 1.0, 1.0};
2117 Vector3 red_yuv = RGBToYUV(red, yuv_color_space);
2118 Vector3 green_yuv = RGBToYUV(green, yuv_color_space);
2119 Vector3 blue_yuv = RGBToYUV(blue, yuv_color_space);
2120 Vector3 white_yuv = RGBToYUV(white, yuv_color_space);
2121 std::vector<Vector3> yuvs{red_yuv, green_yuv, blue_yuv, white_yuv};
2122 std::vector<uint8_t> y_data;
2123 std::vector<uint8_t> uv_data;
2124 for (int i = 0; i < 4; i++) {
2125 auto yuv = yuvs[i];
2126 uint8_t y = std::round(yuv.x * 255.0);
2127 uint8_t u = std::round(yuv.y * 255.0);
2128 uint8_t v = std::round(yuv.z * 255.0);
2129 for (int j = 0; j < 16; j++) {
2130 y_data.push_back(y);
2131 }
2132 for (int j = 0; j < 8; j++) {
2133 uv_data.push_back(j % 2 == 0 ? u : v);
2134 }
2135 }
2136 impeller::TextureDescriptor y_texture_descriptor;
2137 y_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
2138 y_texture_descriptor.format = PixelFormat::kR8UNormInt;
2139 y_texture_descriptor.size = {8, 8};
2140 auto y_texture =
2141 context->GetResourceAllocator()->CreateTexture(y_texture_descriptor);
2142 auto y_mapping = std::make_shared<fml::DataMapping>(y_data);
2143 if (!y_texture->SetContents(y_mapping)) {
2144 FML_DLOG(ERROR) << "Could not copy contents into Y texture.";
2145 }
2146
2147 impeller::TextureDescriptor uv_texture_descriptor;
2148 uv_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
2149 uv_texture_descriptor.format = PixelFormat::kR8G8UNormInt;
2150 uv_texture_descriptor.size = {4, 4};
2151 auto uv_texture =
2152 context->GetResourceAllocator()->CreateTexture(uv_texture_descriptor);
2153 auto uv_mapping = std::make_shared<fml::DataMapping>(uv_data);
2154 if (!uv_texture->SetContents(uv_mapping)) {
2155 FML_DLOG(ERROR) << "Could not copy contents into UV texture.";
2156 }
2157
2158 return {y_texture, uv_texture};
2159 }

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

Referenced by TEST_P().

## ◆ DART_TEST_CASE() [1/4]

impeller::testing::DART_TEST_CASE | ( | canCreateRenderPassAndSubmit |  | ) |

## ◆ DART_TEST_CASE() [2/4]

impeller::testing::DART_TEST_CASE | ( | canCreateShaderLibrary |  | ) |

These test entries correspond to Dart functions located in `flutter/impeller/fixtures/dart_tests.dart`

## ◆ DART_TEST_CASE() [3/4]

impeller::testing::DART_TEST_CASE | ( | canReflectUniformStructs |  | ) |

## ◆ DART_TEST_CASE() [4/4]

impeller::testing::DART_TEST_CASE | ( | uniformBindFailsForInvalidHostBufferOffset |  | ) |

## ◆ flip_lr()

template<typename R >

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

Definition at line 1279 of file rect_unittests.cc.

1279 {
1280 return R::MakeLTRB(rect.GetRight(), rect.GetTop(), //
1281 rect.GetLeft(), rect.GetBottom());
1282 }

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 1291 of file rect_unittests.cc.

1291 {
1292 return flip_lr(flip_tb(rect));
1293 }

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 1285 of file rect_unittests.cc.

1285 {
1286 return R::MakeLTRB(rect.GetLeft(), rect.GetBottom(), //
1287 rect.GetRight(), rect.GetTop());
1288 }

Referenced by flip_lrtb(), and TEST().

## ◆ GetBlendModeSelection()

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

Definition at line 1040 of file aiks_unittests.cc.

1040 {
1041 std::vector<const char*> blend_mode_names;
1042 std::vector<BlendMode> blend_mode_values;
1043 {
1044 const std::vector<std::tuple<const char*, BlendMode>> blends = {
1045 IMPELLER_FOR_EACH_BLEND_MODE(BLEND_MODE_TUPLE)};
1046 assert(blends.size() ==
1047 static_cast<size_t>(Entity::kLastAdvancedBlendMode) + 1);
1048 for (const auto& [name, mode] : blends) {
1049 blend_mode_names.push_back(name);
1050 blend_mode_values.push_back(mode);
1051 }
1052 }
1053
1054 return {blend_mode_names, blend_mode_values};
1055 }

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

Referenced by TEST_P().

## ◆ GetCoverageOfFirstEntity()

template<typename Contents >

static std::optional<Rect> impeller::testing::GetCoverageOfFirstEntity | ( | const Picture & | picture | ) |
| static

Definition at line 1752 of file dl_unittests.cc.

1752 {
1753 std::optional<Rect> coverage;
1754 picture.pass->IterateAllEntities([&coverage](Entity& entity) {
1755 if (std::static_pointer_cast<Contents>(entity.GetContents())) {
1756 auto contents = std::static_pointer_cast<Contents>(entity.GetContents());
1757 Entity entity;
1758 coverage = contents->GetCoverage(entity);
1759 return false;
1760 }
1761 return true;
1762 });
1763 return coverage;
1764 }

References impeller::Entity::GetContents(), and impeller::Picture::pass.

## ◆ INSTANTIATE_COMPUTE_SUITE()

impeller::testing::INSTANTIATE_COMPUTE_SUITE | ( | ComputeSubgroupTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [1/7]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [2/7]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | BlitPassTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [3/7]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [4/7]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [5/7]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [6/7]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [7/7]

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

## ◆ 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 28 of file renderer_dart_unittests.cc.

28 {
29 auto fixture =
30 flutter::testing::OpenFixtureAsMapping("playground.shaderbundle");
31 auto library = flutter::gpu::ShaderLibrary::MakeFromFlatbuffer(
32 backend_type, std::move(fixture));
33 flutter::gpu::ShaderLibrary::SetOverride(library);
34 }

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

## ◆ MaskBlurVariantTest()

static Picture impeller::testing::MaskBlurVariantTest | ( | const AiksTest & | test_context,
|  | const MaskBlurTestConfig & | config
| ) |  |
| static

Definition at line 294 of file aiks_blur_unittests.cc.

295 {
296 Canvas canvas;
297 canvas.Scale(test_context.GetContentScale());
298 canvas.Scale(Vector2{0.8f, 0.8f});
299 Paint paint;
300 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
301 .style = FilterContents::BlurStyle::kNormal,
302 .sigma = Sigma{1},
303 };
304
305 canvas.DrawPaint({.color = Color::AntiqueWhite()});
306
307 paint.mask_blur_descriptor->style = config.style;
308 paint.mask_blur_descriptor->sigma = Sigma{config.sigma};
309 paint.image_filter = config.image_filter;
310 paint.invert_colors = config.invert_colors;
311 paint.blend_mode = config.blend_mode;
312
313 const Scalar x = 50;
314 const Scalar radius = 20.0f;
315 const Scalar y_spacing = 100.0f;
316
317 Scalar y = 50;
318 paint.color = Color::Crimson().WithAlpha(config.alpha);
319 canvas.DrawRect(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
320 radius, 60.0f - radius),
321 paint);
322
323 y += y_spacing;
324 paint.color = Color::Blue().WithAlpha(config.alpha);
325 canvas.DrawCircle({x + 25, y + 25}, radius, paint);
326
327 y += y_spacing;
328 paint.color = Color::Green().WithAlpha(config.alpha);
329 canvas.DrawOval(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
330 radius, 60.0f - radius),
331 paint);
332
333 y += y_spacing;
334 paint.color = Color::Purple().WithAlpha(config.alpha);
335 canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
336 {radius, radius}, //
337 paint);
338
339 y += y_spacing;
340 paint.color = Color::Orange().WithAlpha(config.alpha);
341 canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
342 {radius, 5.0f}, paint);
343
344 y += y_spacing;
345 paint.color = Color::Maroon().WithAlpha(config.alpha);
346 canvas.DrawPath(PathBuilder{}
347 .MoveTo({x + 0, y + 60})
348 .LineTo({x + 30, y + 0})
349 .LineTo({x + 60, y + 60})
350 .Close()
351 .TakePath(),
352 paint);
353
354 y += y_spacing;
355 paint.color = Color::Maroon().WithAlpha(config.alpha);
356 canvas.DrawPath(PathBuilder{}
357 .AddArc(Rect::MakeXYWH(x + 5, y, 50, 50),
358 Radians{kPi / 2}, Radians{kPi})
359 .AddArc(Rect::MakeXYWH(x + 25, y, 50, 50),
360 Radians{kPi / 2}, Radians{kPi})
361 .Close()
362 .TakePath(),
363 paint);
364
365 return canvas.EndRecordingAsPicture();
366 }

References impeller::PathBuilder::AddArc(), impeller::testing::MaskBlurTestConfig::alpha, impeller::Color::AntiqueWhite(), impeller::Paint::blend_mode, impeller::testing::MaskBlurTestConfig::blend_mode, impeller::Color::Blue(), impeller::Close(), impeller::Paint::color, impeller::Color::Crimson(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawOval(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Playground::GetContentScale(), impeller::Color::Green(), impeller::Paint::image_filter, impeller::testing::MaskBlurTestConfig::image_filter, impeller::Paint::invert_colors, impeller::testing::MaskBlurTestConfig::invert_colors, impeller::FilterContents::kNormal, impeller::kPi, impeller::LineTo(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Maroon(), impeller::Paint::mask_blur_descriptor, impeller::PathBuilder::MoveTo(), impeller::Color::Orange(), impeller::Color::Purple(), impeller::Canvas::Scale(), impeller::testing::MaskBlurTestConfig::sigma, impeller::Paint::MaskBlurDescriptor::style, impeller::testing::MaskBlurTestConfig::style, and impeller::Color::WithAlpha().

## ◆ RenderTextInCanvasSkia()

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

Definition at line 714 of file aiks_unittests.cc.

718 {}) {
719 // Draw the baseline.
720 canvas.DrawRect(
721 Rect::MakeXYWH(options.position.x - 50, options.position.y, 900, 10),
722 Paint{.color = Color::Aqua().WithAlpha(0.25)});
723
724 // Mark the point at which the text is drawn.
725 canvas.DrawCircle(options.position, 5.0,
726 Paint{.color = Color::Red().WithAlpha(0.25)});
727
728 // Construct the text blob.
729 auto c_font_fixture = std::string(font_fixture);
730 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
731 if (!mapping) {
732 return false;
733 }
734 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
735 SkFont sk_font(font_mgr->makeFromData(mapping), options.font_size);
736 auto blob = SkTextBlob::MakeFromString(text.c_str(), sk_font);
737 if (!blob) {
738 return false;
739 }
740
741 // Create the Impeller text frame and draw it at the designated baseline.
742 auto frame = MakeTextFrameFromTextBlobSkia(blob);
743
744 Paint text_paint;
745 text_paint.color = options.color;
746 text_paint.mask_blur_descriptor = options.mask_blur_descriptor;
747 canvas.DrawTextFrame(frame, options.position, text_paint);
748 return true;
749 }

Referenced by TEST_P().

## ◆ RenderTextInCanvasSTB()

bool impeller::testing::RenderTextInCanvasSTB | ( | const std::shared_ptr< Context > & | context,
|  | Canvas & | canvas,
|  | const std::string & | text,
|  | const std::string & | font_fixture,
|  | TextRenderOptions | options = `{}`
| ) |  |

Definition at line 751 of file aiks_unittests.cc.

755 {}) {
756 // Draw the baseline.
757 canvas.DrawRect(
758 Rect::MakeXYWH(options.position.x - 50, options.position.y, 900, 10),
759 Paint{.color = Color::Aqua().WithAlpha(0.25)});
760
761 // Mark the point at which the text is drawn.
762 canvas.DrawCircle(options.position, 5.0,
763 Paint{.color = Color::Red().WithAlpha(0.25)});
764
765 // Construct the text blob.
766 auto mapping = flutter::testing::OpenFixtureAsMapping(font_fixture.c_str());
767 if (!mapping) {
768 return false;
769 }
770 auto typeface_stb = std::make_shared<TypefaceSTB>(std::move(mapping));
771
772 auto frame = MakeTextFrameSTB(
773 typeface_stb, Font::Metrics{.point_size = options.font_size}, text);
774
775 Paint text_paint;
776 text_paint.color = options.color;
777 canvas.DrawTextFrame(frame, options.position, text_paint);
778 return true;
779 }

Referenced by TEST_P().

## ◆ RGBToYUV()

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

Definition at line 2093 of file entity_unittests.cc.

2093 {
2094 Vector3 yuv;
2095 switch (yuv_color_space) {
2096 case YUVColorSpace::kBT601FullRange:
2097 yuv.x = rgb.x * 0.299 + rgb.y * 0.587 + rgb.z * 0.114;
2098 yuv.y = rgb.x * -0.169 + rgb.y * -0.331 + rgb.z * 0.5 + 0.5;
2099 yuv.z = rgb.x * 0.5 + rgb.y * -0.419 + rgb.z * -0.081 + 0.5;
2100 break;
2101 case YUVColorSpace::kBT601LimitedRange:
2102 yuv.x = rgb.x * 0.257 + rgb.y * 0.516 + rgb.z * 0.100 + 0.063;
2103 yuv.y = rgb.x * -0.145 + rgb.y * -0.291 + rgb.z * 0.439 + 0.5;
2104 yuv.z = rgb.x * 0.429 + rgb.y * -0.368 + rgb.z * -0.071 + 0.5;
2105 break;
2106 }
2107 return yuv;
2108 }

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 1305 of file rect_unittests.cc.

1305 {
1306 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1307 FML_DCHECK(index >= 0 && index <= 3);
1308 Scalar x = ((index & (1 << 0)) != 0) ? nan : point.x;
1309 Scalar y = ((index & (1 << 1)) != 0) ? nan : point.y;
1310 return Point(x, y);
1311 }

References 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 1295 of file rect_unittests.cc.

1295 {
1296 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1297 FML_DCHECK(index >= 0 && index <= 15);
1298 Scalar l = ((index & (1 << 0)) != 0) ? nan : rect.GetLeft();
1299 Scalar t = ((index & (1 << 1)) != 0) ? nan : rect.GetTop();
1300 Scalar r = ((index & (1 << 2)) != 0) ? nan : rect.GetRight();
1301 Scalar b = ((index & (1 << 3)) != 0) ? nan : rect.GetBottom();
1302 return Rect::MakeLTRB(l, t, r, b);
1303 }

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

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | DisableLocalBoundsRectForFilteredSaveLayers |
| ) |  |

Definition at line 340 of file canvas_unittests.cc.

340 {
341 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
342
343 Canvas canvas(initial_cull);
344 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
345
346 canvas.Save();
347 canvas.SaveLayer(
348 Paint{.image_filter = ImageFilter::MakeBlur(
349 Sigma(10), Sigma(10), FilterContents::BlurStyle::kNormal,
350 Entity::TileMode::kDecal)});
351 ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
352
353 canvas.Restore();
354 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
355 }

References impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Paint::image_filter, impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::Canvas::SaveLayer().

## ◆ TEST() [2/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | EmptyCullRect |
| ) |  |

Definition at line 18 of file canvas_unittests.cc.

18 {
19 Canvas canvas;
20
21 ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
22 }

References impeller::Canvas::GetCurrentLocalCullingBounds().

## ◆ TEST() [3/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | InitialCullRect |
| ) |  |

Definition at line 24 of file canvas_unittests.cc.

24 {
25 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
26
27 Canvas canvas(initial_cull);
28
29 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
30 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), initial_cull);
31 }

References impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [4/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | PathClipDiffAgainstEmptyCullRect |
| ) |  |

Definition at line 277 of file canvas_unittests.cc.

277 {
278 PathBuilder builder;
279 builder.AddRect(Rect::MakeXYWH(5, 5, 1, 1));
280 builder.AddRect(Rect::MakeXYWH(5, 14, 1, 1));
281 builder.AddRect(Rect::MakeXYWH(14, 5, 1, 1));
282 builder.AddRect(Rect::MakeXYWH(14, 14, 1, 1));
283 Path path = builder.TakePath();
284
285 Canvas canvas;
286 canvas.ClipPath(path, Entity::ClipOperation::kDifference);
287
288 ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
289 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::ClipPath(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [5/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | PathClipDiffAgainstFullyCoveredCullRect |
| ) |  |

Definition at line 325 of file canvas_unittests.cc.

325 {
326 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
327 PathBuilder builder;
328 builder.AddRect(Rect::MakeXYWH(0, 0, 100, 100));
329 Path path = builder.TakePath();
330 // Diff clip of Paths is ignored due to complexity
331 Rect result_cull = Rect::MakeXYWH(5, 5, 10, 10);
332
333 Canvas canvas(initial_cull);
334 canvas.ClipPath(path, Entity::ClipOperation::kDifference);
335
336 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
337 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
338 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::ClipPath(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [6/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | PathClipDiffAgainstNonCoveredCullRect |
| ) |  |

Definition at line 308 of file canvas_unittests.cc.

308 {
309 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
310 PathBuilder builder;
311 builder.AddRect(Rect::MakeXYWH(5, 5, 1, 1));
312 builder.AddRect(Rect::MakeXYWH(5, 14, 1, 1));
313 builder.AddRect(Rect::MakeXYWH(14, 5, 1, 1));
314 builder.AddRect(Rect::MakeXYWH(14, 14, 1, 1));
315 Path path = builder.TakePath();
316 Rect result_cull = Rect::MakeXYWH(0, 0, 10, 10);
317
318 Canvas canvas(initial_cull);
319 canvas.ClipPath(path, Entity::ClipOperation::kDifference);
320
321 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
322 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
323 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::ClipPath(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [7/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | PathClipIntersectAgainstCullRect |
| ) |  |

Definition at line 291 of file canvas_unittests.cc.

291 {
292 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
293 PathBuilder builder;
294 builder.AddRect(Rect::MakeXYWH(5, 5, 1, 1));
295 builder.AddRect(Rect::MakeXYWH(5, 14, 1, 1));
296 builder.AddRect(Rect::MakeXYWH(14, 5, 1, 1));
297 builder.AddRect(Rect::MakeXYWH(14, 14, 1, 1));
298 Path path = builder.TakePath();
299 Rect result_cull = Rect::MakeXYWH(5, 5, 5, 5);
300
301 Canvas canvas(initial_cull);
302 canvas.ClipPath(path, Entity::ClipOperation::kIntersect);
303
304 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
305 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
306 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::ClipPath(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kIntersect, impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [8/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | PathClipIntersectAgainstEmptyCullRect |
| ) |  |

Definition at line 261 of file canvas_unittests.cc.

261 {
262 PathBuilder builder;
263 builder.AddRect(Rect::MakeXYWH(5, 5, 1, 1));
264 builder.AddRect(Rect::MakeXYWH(5, 14, 1, 1));
265 builder.AddRect(Rect::MakeXYWH(14, 5, 1, 1));
266 builder.AddRect(Rect::MakeXYWH(14, 14, 1, 1));
267 Path path = builder.TakePath();
268 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
269
270 Canvas canvas;
271 canvas.ClipPath(path, Entity::ClipOperation::kIntersect);
272
273 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
274 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), rect_clip);
275 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::ClipPath(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kIntersect, impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [9/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffAboveCullRect |
| ) |  |

Definition at line 98 of file canvas_unittests.cc.

98 {
99 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
100 Rect rect_clip = Rect::MakeXYWH(0, 0, 20, 4);
101 Rect result_cull = Rect::MakeXYWH(5, 5, 10, 10);
102
103 Canvas canvas(initial_cull);
104 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
105
106 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
107 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
108 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [10/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffAgainstEmptyCullRect |
| ) |  |

Definition at line 65 of file canvas_unittests.cc.

65 {
66 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
67
68 Canvas canvas;
69 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
70
71 ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
72 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [11/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffAgainstHCoveredCullRect |
| ) |  |

Definition at line 158 of file canvas_unittests.cc.

158 {
159 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
160 Rect rect_clip = Rect::MakeXYWH(0, 5, 10, 10);
161 Rect result_cull = Rect::MakeXYWH(0, 0, 10, 5);
162
163 Canvas canvas(initial_cull);
164 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
165
166 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
167 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
168 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [12/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffAgainstNonCoveredCullRect |
| ) |  |

Definition at line 86 of file canvas_unittests.cc.

86 {
87 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
88 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
89 Rect result_cull = Rect::MakeXYWH(0, 0, 10, 10);
90
91 Canvas canvas(initial_cull);
92 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
93
94 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
95 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
96 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [13/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffAgainstVCoveredCullRect |
| ) |  |

Definition at line 146 of file canvas_unittests.cc.

146 {
147 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
148 Rect rect_clip = Rect::MakeXYWH(5, 0, 10, 10);
149 Rect result_cull = Rect::MakeXYWH(0, 0, 5, 10);
150
151 Canvas canvas(initial_cull);
152 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
153
154 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
155 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
156 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [14/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffBelowCullRect |
| ) |  |

Definition at line 110 of file canvas_unittests.cc.

110 {
111 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
112 Rect rect_clip = Rect::MakeXYWH(0, 16, 20, 4);
113 Rect result_cull = Rect::MakeXYWH(5, 5, 10, 10);
114
115 Canvas canvas(initial_cull);
116 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
117
118 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
119 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
120 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [15/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffLeftOfCullRect |
| ) |  |

Definition at line 122 of file canvas_unittests.cc.

122 {
123 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
124 Rect rect_clip = Rect::MakeXYWH(0, 0, 4, 20);
125 Rect result_cull = Rect::MakeXYWH(5, 5, 10, 10);
126
127 Canvas canvas(initial_cull);
128 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
129
130 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
131 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
132 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [16/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffRightOfCullRect |
| ) |  |

Definition at line 134 of file canvas_unittests.cc.

134 {
135 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
136 Rect rect_clip = Rect::MakeXYWH(16, 0, 4, 20);
137 Rect result_cull = Rect::MakeXYWH(5, 5, 10, 10);
138
139 Canvas canvas(initial_cull);
140 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
141
142 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
143 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
144 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [17/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipIntersectAgainstCullRect |
| ) |  |

Definition at line 74 of file canvas_unittests.cc.

74 {
75 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
76 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
77 Rect result_cull = Rect::MakeXYWH(5, 5, 5, 5);
78
79 Canvas canvas(initial_cull);
80 canvas.ClipRect(rect_clip, Entity::ClipOperation::kIntersect);
81
82 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
83 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
84 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kIntersect, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [18/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipIntersectAgainstEmptyCullRect |
| ) |  |

Definition at line 55 of file canvas_unittests.cc.

55 {
56 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
57
58 Canvas canvas;
59 canvas.ClipRect(rect_clip, Entity::ClipOperation::kIntersect);
60
61 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
62 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), rect_clip);
63 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kIntersect, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [19/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipDiffAgainstEmptyCullRect |
| ) |  |

Definition at line 180 of file canvas_unittests.cc.

180 {
181 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
182
183 Canvas canvas;
184 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
185
186 ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
187 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [20/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipDiffAgainstHFullyCoveredCullRect |
| ) |  |

Definition at line 249 of file canvas_unittests.cc.

249 {
250 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
251 Rect rect_clip = Rect::MakeXYWH(-2, 5, 14, 10);
252 Rect result_cull = Rect::MakeXYWH(0, 0, 10, 5);
253
254 Canvas canvas(initial_cull);
255 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
256
257 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
258 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
259 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [21/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipDiffAgainstHPartiallyCoveredCullRect |
| ) |  |

Definition at line 237 of file canvas_unittests.cc.

237 {
238 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
239 Rect rect_clip = Rect::MakeXYWH(0, 5, 10, 10);
240 Rect result_cull = Rect::MakeXYWH(0, 0, 10, 6);
241
242 Canvas canvas(initial_cull);
243 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
244
245 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
246 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
247 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [22/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipDiffAgainstNonCoveredCullRect |
| ) |  |

Definition at line 201 of file canvas_unittests.cc.

201 {
202 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
203 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
204 Rect result_cull = Rect::MakeXYWH(0, 0, 10, 10);
205
206 Canvas canvas(initial_cull);
207 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
208
209 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
210 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
211 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [23/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipDiffAgainstVFullyCoveredCullRect |
| ) |  |

Definition at line 225 of file canvas_unittests.cc.

225 {
226 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
227 Rect rect_clip = Rect::MakeXYWH(5, -2, 10, 14);
228 Rect result_cull = Rect::MakeXYWH(0, 0, 5, 10);
229
230 Canvas canvas(initial_cull);
231 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
232
233 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
234 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
235 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [24/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipDiffAgainstVPartiallyCoveredCullRect |
| ) |  |

Definition at line 213 of file canvas_unittests.cc.

213 {
214 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
215 Rect rect_clip = Rect::MakeXYWH(5, 0, 10, 10);
216 Rect result_cull = Rect::MakeXYWH(0, 0, 6, 10);
217
218 Canvas canvas(initial_cull);
219 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kDifference);
220
221 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
222 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
223 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [25/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipIntersectAgainstCullRect |
| ) |  |

Definition at line 189 of file canvas_unittests.cc.

189 {
190 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
191 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
192 Rect result_cull = Rect::MakeXYWH(5, 5, 5, 5);
193
194 Canvas canvas(initial_cull);
195 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kIntersect);
196
197 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
198 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
199 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kIntersect, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [26/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipIntersectAgainstEmptyCullRect |
| ) |  |

Definition at line 170 of file canvas_unittests.cc.

170 {
171 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
172
173 Canvas canvas;
174 canvas.ClipRRect(rect_clip, {1, 1}, Entity::ClipOperation::kIntersect);
175
176 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
177 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), rect_clip);
178 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kIntersect, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [27/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | ScaledCullRect |
| ) |  |

Definition at line 44 of file canvas_unittests.cc.

44 {
45 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
46 Rect scaled_cull = Rect::MakeXYWH(10, 10, 20, 20);
47
48 Canvas canvas(initial_cull);
49 canvas.Scale(Vector2(0.5, 0.5));
50
51 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
52 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), scaled_cull);
53 }

References impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Canvas::Scale().

## ◆ TEST() [28/370]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | TranslatedCullRect |
| ) |  |

Definition at line 33 of file canvas_unittests.cc.

33 {
34 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
35 Rect translated_cull = Rect::MakeXYWH(0, 0, 10, 10);
36
37 Canvas canvas(initial_cull);
38 canvas.Translate(Vector3(5, 5, 0));
39
40 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
41 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), translated_cull);
42 }

References impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Canvas::Translate().

## ◆ TEST() [29/370]

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 }

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

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

Definition at line 35 of file allocator_vk_unittests.cc.

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

References impeller::AllocatorVK::FindMemoryTypeIndex().

## ◆ TEST() [31/370]

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

Definition at line 50 of file allocator_vk_unittests.cc.

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

References impeller::AllocatorVK::FindMemoryTypeIndex().

## ◆ TEST() [32/370]

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

Definition at line 16 of file allocator_vk_unittests.cc.

16 {
17 EXPECT_EQ(AllocatorVK::ToVKImageUsageFlags(
18 PixelFormat::kR8G8B8A8UNormInt,
19 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget),
20 StorageMode::kDeviceTransient,
21 /*supports_memoryless_textures=*/true),
22 vk::ImageUsageFlagBits::eInputAttachment |
23 vk::ImageUsageFlagBits::eColorAttachment |
24 vk::ImageUsageFlagBits::eTransientAttachment);
25
26 EXPECT_EQ(AllocatorVK::ToVKImageUsageFlags(
27 PixelFormat::kD24UnormS8Uint,
28 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget),
29 StorageMode::kDeviceTransient,
30 /*supports_memoryless_textures=*/true),
31 vk::ImageUsageFlagBits::eDepthStencilAttachment |
32 vk::ImageUsageFlagBits::eTransientAttachment);
33 }

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

## ◆ TEST() [33/370]

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

Definition at line 266 of file base_unittests.cc.

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

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

## ◆ TEST() [34/370]

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

Definition at line 257 of file base_unittests.cc.

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

## ◆ TEST() [35/370]

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

Definition at line 250 of file base_unittests.cc.

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

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

## ◆ TEST() [36/370]

impeller::testing::TEST | ( | BlitCommandVkTest | ,
|  | BlitCopyBufferToTextureCommandVK |
| ) |  |

Definition at line 49 of file blit_command_vk_unittests.cc.

49 {
50 auto context = MockVulkanContextBuilder().Build();
51 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
52 BlitCopyBufferToTextureCommandVK cmd;
53 cmd.destination = context->GetResourceAllocator()->CreateTexture({
54 .format = PixelFormat::kR8G8B8A8UNormInt,
55 .size = ISize(100, 100),
56 });
57 cmd.source =
58 DeviceBuffer::AsBufferView(context->GetResourceAllocator()->CreateBuffer({
59 .size = 1,
60 }));
61 bool result = cmd.Encode(*encoder.get());
62 EXPECT_TRUE(result);
63 EXPECT_TRUE(encoder->IsTracking(cmd.source.buffer));
64 EXPECT_TRUE(encoder->IsTracking(cmd.destination));
65 }

References impeller::DeviceBuffer::AsBufferView(), impeller::BufferView::buffer, impeller::BlitCopyBufferToTextureCommand::destination, impeller::BlitCopyBufferToTextureCommandVK::Encode(), impeller::kR8G8B8A8UNormInt, and impeller::BlitCopyBufferToTextureCommand::source.

## ◆ TEST() [37/370]

impeller::testing::TEST | ( | BlitCommandVkTest | ,
|  | BlitCopyTextureToBufferCommandVK |
| ) |  |

Definition at line 32 of file blit_command_vk_unittests.cc.

32 {
33 auto context = MockVulkanContextBuilder().Build();
34 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
35 BlitCopyTextureToBufferCommandVK cmd;
36 cmd.source = context->GetResourceAllocator()->CreateTexture({
37 .format = PixelFormat::kR8G8B8A8UNormInt,
38 .size = ISize(100, 100),
39 });
40 cmd.destination = context->GetResourceAllocator()->CreateBuffer({
41 .size = 1,
42 });
43 bool result = cmd.Encode(*encoder.get());
44 EXPECT_TRUE(result);
45 EXPECT_TRUE(encoder->IsTracking(cmd.source));
46 EXPECT_TRUE(encoder->IsTracking(cmd.destination));
47 }

References impeller::BlitCopyTextureToBufferCommand::destination, impeller::BlitCopyTextureToBufferCommandVK::Encode(), impeller::kR8G8B8A8UNormInt, and impeller::BlitCopyTextureToBufferCommand::source.

## ◆ TEST() [38/370]

impeller::testing::TEST | ( | BlitCommandVkTest | ,
|  | BlitCopyTextureToTextureCommandVK |
| ) |  |

Definition at line 13 of file blit_command_vk_unittests.cc.

13 {
14 auto context = MockVulkanContextBuilder().Build();
15 auto pool = context->GetCommandPoolRecycler()->Get();
16 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
17 BlitCopyTextureToTextureCommandVK cmd;
18 cmd.source = context->GetResourceAllocator()->CreateTexture({
19 .format = PixelFormat::kR8G8B8A8UNormInt,
20 .size = ISize(100, 100),
21 });
22 cmd.destination = context->GetResourceAllocator()->CreateTexture({
23 .format = PixelFormat::kR8G8B8A8UNormInt,
24 .size = ISize(100, 100),
25 });
26 bool result = cmd.Encode(*encoder.get());
27 EXPECT_TRUE(result);
28 EXPECT_TRUE(encoder->IsTracking(cmd.source));
29 EXPECT_TRUE(encoder->IsTracking(cmd.destination));
30 }

References impeller::BlitCopyTextureToTextureCommand::destination, impeller::BlitCopyTextureToTextureCommandVK::Encode(), impeller::kR8G8B8A8UNormInt, and impeller::BlitCopyTextureToTextureCommand::source.

## ◆ TEST() [39/370]

impeller::testing::TEST | ( | BlitCommandVkTest | ,
|  | BlitGenerateMipmapCommandVK |
| ) |  |

Definition at line 67 of file blit_command_vk_unittests.cc.

67 {
68 auto context = MockVulkanContextBuilder().Build();
69 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
70 BlitGenerateMipmapCommandVK cmd;
71 cmd.texture = context->GetResourceAllocator()->CreateTexture({
72 .format = PixelFormat::kR8G8B8A8UNormInt,
73 .size = ISize(100, 100),
74 .mip_count = 2,
75 });
76 bool result = cmd.Encode(*encoder.get());
77 EXPECT_TRUE(result);
78 EXPECT_TRUE(encoder->IsTracking(cmd.texture));
79 }

References impeller::BlitGenerateMipmapCommandVK::Encode(), impeller::kR8G8B8A8UNormInt, and impeller::BlitGenerateMipmapCommand::texture.

## ◆ TEST() [40/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | ClipOval |
| ) |  |

Definition at line 220 of file canvas_recorder_unittests.cc.

220 {
221 CanvasRecorder<Serializer> recorder;
222 recorder.ClipOval({});
223 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kClipOval);
224 }

References impeller::kClipOval.

## ◆ TEST() [41/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | ClipPath |
| ) |  |

Definition at line 208 of file canvas_recorder_unittests.cc.

208 {
209 CanvasRecorder<Serializer> recorder;
210 recorder.ClipPath({});
211 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kClipPath);
212 }

References impeller::kClipPath.

## ◆ TEST() [42/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | ClipRect |
| ) |  |

Definition at line 214 of file canvas_recorder_unittests.cc.

214 {
215 CanvasRecorder<Serializer> recorder;
216 recorder.ClipRect({});
217 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kClipRect);
218 }

References impeller::kClipRect.

## ◆ TEST() [43/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | ClipRRect |
| ) |  |

Definition at line 226 of file canvas_recorder_unittests.cc.

226 {
227 CanvasRecorder<Serializer> recorder;
228 recorder.ClipRRect({}, {});
229 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kClipRRect);
230 }

References impeller::kClipRRect.

## ◆ TEST() [44/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | Concat |
| ) |  |

Definition at line 105 of file canvas_recorder_unittests.cc.

105 {
106 CanvasRecorder<Serializer> recorder;
107 recorder.Concat(Matrix());
108 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kConcat);
109 }

References impeller::kConcat.

## ◆ TEST() [45/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | DrawAtlas |
| ) |  |

Definition at line 247 of file canvas_recorder_unittests.cc.

247 {
248 CanvasRecorder<Serializer> recorder;
249 recorder.DrawAtlas({}, {}, {}, {}, {}, {}, {}, {});
250 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawAtlas);
251 }

References impeller::kDrawAtlas.

## ◆ TEST() [46/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | DrawCircle |
| ) |  |

Definition at line 183 of file canvas_recorder_unittests.cc.

183 {
184 CanvasRecorder<Serializer> recorder;
185 recorder.DrawCircle(Point(), 0, Paint());
186 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawCircle);
187 }

References impeller::kDrawCircle.

## ◆ TEST() [47/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | DrawImage |
| ) |  |

Definition at line 195 of file canvas_recorder_unittests.cc.

195 {
196 CanvasRecorder<Serializer> recorder;
197 recorder.DrawImage({}, {}, {}, {});
198 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawImage);
199 }

References impeller::kDrawImage.

## ◆ TEST() [48/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | DrawImageRect |
| ) |  |

Definition at line 201 of file canvas_recorder_unittests.cc.

201 {
202 CanvasRecorder<Serializer> recorder;
203 recorder.DrawImageRect({}, {}, {}, {}, {}, SourceRectConstraint::kFast);
204 ASSERT_EQ(recorder.GetSerializer().last_op_,
205 CanvasRecorderOp::kDrawImageRect);
206 }

References impeller::kDrawImageRect, and impeller::kFast.

## ◆ TEST() [49/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | DrawLine |
| ) |  |

Definition at line 159 of file canvas_recorder_unittests.cc.

159 {
160 CanvasRecorder<Serializer> recorder;
161 recorder.DrawLine(Point(), Point(), Paint());
162 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawLine);
163 }

References impeller::kDrawLine.

## ◆ TEST() [50/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | DrawOval |
| ) |  |

Definition at line 171 of file canvas_recorder_unittests.cc.

171 {
172 CanvasRecorder<Serializer> recorder;
173 recorder.DrawOval(Rect(), Paint());
174 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawOval);
175 }

References impeller::kDrawOval.

## ◆ TEST() [51/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | DrawPaint |
| ) |  |

Definition at line 153 of file canvas_recorder_unittests.cc.

153 {
154 CanvasRecorder<Serializer> recorder;
155 recorder.DrawPaint(Paint());
156 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawPaint);
157 }

References impeller::kDrawPaint.

## ◆ TEST() [52/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | DrawPath |
| ) |  |

Definition at line 147 of file canvas_recorder_unittests.cc.

147 {
148 CanvasRecorder<Serializer> recorder;
149 recorder.DrawPath(Path(), Paint());
150 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawPath);
151 }

References impeller::kDrawPath.

## ◆ TEST() [53/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | DrawPoints |
| ) |  |

Definition at line 189 of file canvas_recorder_unittests.cc.

189 {
190 CanvasRecorder<Serializer> recorder;
191 recorder.DrawPoints(std::vector<Point>{}, 0, Paint(), PointStyle::kRound);
192 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawPoints);
193 }

References impeller::kDrawPoints, and impeller::kRound.

## ◆ TEST() [54/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | DrawRect |
| ) |  |

Definition at line 165 of file canvas_recorder_unittests.cc.

165 {
166 CanvasRecorder<Serializer> recorder;
167 recorder.DrawRect(Rect(), Paint());
168 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawRect);
169 }

References impeller::kDrawRect.

## ◆ TEST() [55/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | DrawRRect |
| ) |  |

Definition at line 177 of file canvas_recorder_unittests.cc.

177 {
178 CanvasRecorder<Serializer> recorder;
179 recorder.DrawRRect(Rect(), {}, Paint());
180 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawRRect);
181 }

References impeller::kDrawRRect.

## ◆ TEST() [56/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | DrawTextFrame |
| ) |  |

Definition at line 232 of file canvas_recorder_unittests.cc.

232 {
233 CanvasRecorder<Serializer> recorder;
234 recorder.DrawTextFrame({}, {}, {});
235 ASSERT_EQ(recorder.GetSerializer().last_op_,
236 CanvasRecorderOp::kDrawTextFrame);
237 }

References impeller::kDrawTextFrame.

## ◆ TEST() [57/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | DrawVertices |
| ) |  |

Definition at line 239 of file canvas_recorder_unittests.cc.

239 {
240 CanvasRecorder<Serializer> recorder;
241 auto geometry = std::shared_ptr<VerticesGeometry>(
242 new VerticesGeometry({}, {}, {}, {}, {}, {}));
243 recorder.DrawVertices(geometry, {}, {});
244 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawVertices);
245 }

References impeller::kDrawVertices.

## ◆ TEST() [58/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | PreConcat |
| ) |  |

Definition at line 111 of file canvas_recorder_unittests.cc.

111 {
112 CanvasRecorder<Serializer> recorder;
113 recorder.PreConcat(Matrix());
114 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kPreConcat);
115 }

References impeller::kPreConcat.

## ◆ TEST() [59/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | ResetTransform |
| ) |  |

Definition at line 92 of file canvas_recorder_unittests.cc.

92 {
93 CanvasRecorder<Serializer> recorder;
94 recorder.ResetTransform();
95 ASSERT_EQ(recorder.GetSerializer().last_op_,
96 CanvasRecorderOp::kResetTransform);
97 }

References impeller::kResetTransform.

## ◆ TEST() [60/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | Restore |
| ) |  |

Definition at line 78 of file canvas_recorder_unittests.cc.

78 {
79 CanvasRecorder<Serializer> recorder;
80 recorder.Restore();
81 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kRestore);
82 }

References impeller::kRestore.

## ◆ TEST() [61/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | RestoreToCount |
| ) |  |

Definition at line 84 of file canvas_recorder_unittests.cc.

84 {
85 CanvasRecorder<Serializer> recorder;
86 recorder.Save();
87 recorder.RestoreToCount(0);
88 ASSERT_EQ(recorder.GetSerializer().last_op_,
89 CanvasRecorderOp::kRestoreToCount);
90 }

References impeller::kRestoreToCount.

## ◆ TEST() [62/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | Rotate |
| ) |  |

Definition at line 141 of file canvas_recorder_unittests.cc.

141 {
142 CanvasRecorder<Serializer> recorder;
143 recorder.Rotate(Radians(0));
144 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kRotate);
145 }

References impeller::kRotate.

## ◆ TEST() [63/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | Save |
| ) |  |

Definition at line 65 of file canvas_recorder_unittests.cc.

65 {
66 CanvasRecorder<Serializer> recorder;
67 recorder.Save();
68 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kSave);
69 }

References impeller::kSave.

## ◆ TEST() [64/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | SaveLayer |
| ) |  |

Definition at line 71 of file canvas_recorder_unittests.cc.

71 {
72 CanvasRecorder<Serializer> recorder;
73 Paint paint;
74 recorder.SaveLayer(paint);
75 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kSaveLayer);
76 }

References impeller::kSaveLayer.

## ◆ TEST() [65/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | Scale2 |
| ) |  |

Definition at line 123 of file canvas_recorder_unittests.cc.

123 {
124 CanvasRecorder<Serializer> recorder;
125 recorder.Scale(Vector2());
126 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kScale2);
127 }

References impeller::kScale2.

## ◆ TEST() [66/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | Scale3 |
| ) |  |

Definition at line 129 of file canvas_recorder_unittests.cc.

129 {
130 CanvasRecorder<Serializer> recorder;
131 recorder.Scale(Vector3());
132 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kScale3);
133 }

References impeller::kScale3.

## ◆ TEST() [67/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | Skew |
| ) |  |

Definition at line 135 of file canvas_recorder_unittests.cc.

135 {
136 CanvasRecorder<Serializer> recorder;
137 recorder.Skew(0, 0);
138 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kSkew);
139 }

References impeller::kSkew.

## ◆ TEST() [68/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | Transform |
| ) |  |

Definition at line 99 of file canvas_recorder_unittests.cc.

99 {
100 CanvasRecorder<Serializer> recorder;
101 recorder.Transform(Matrix());
102 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kTransform);
103 }

References impeller::kTransform.

## ◆ TEST() [69/370]

impeller::testing::TEST | ( | CanvasRecorder | ,
|  | Translate |
| ) |  |

Definition at line 117 of file canvas_recorder_unittests.cc.

117 {
118 CanvasRecorder<Serializer> recorder;
119 recorder.Translate(Vector3());
120 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kTranslate);
121 }

References impeller::kTranslate.

## ◆ TEST() [70/370]

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

Definition at line 32 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [71/370]

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

Definition at line 50 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [72/370]

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

Definition at line 60 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [73/370]

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

Definition at line 41 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [74/370]

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

Definition at line 195 of file context_vk_unittests.cc.

196 {
197 ScopedValidationDisable disable_validation;
198 const std::shared_ptr<ContextVK> context =
199 MockVulkanContextBuilder()
200 .SetPhysicalDeviceFormatPropertiesCallback(
201 [](VkPhysicalDevice physicalDevice, VkFormat format,
202 VkFormatProperties* pFormatProperties) {
203 if (format == VK_FORMAT_B8G8R8A8_UNORM) {
204 pFormatProperties->optimalTilingFeatures =
205 static_cast<VkFormatFeatureFlags>(
206 vk::FormatFeatureFlagBits::eColorAttachment);
207 }
208 // Ignore combined depth-stencil formats.
209 })
210 .Build();
211 ASSERT_EQ(context, nullptr);
212 }

## ◆ TEST() [75/370]

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

Definition at line 164 of file context_vk_unittests.cc.

164 {
165 const std::shared_ptr<ContextVK> context =
166 MockVulkanContextBuilder()
167 .SetPhysicalDeviceFormatPropertiesCallback(
168 [](VkPhysicalDevice physicalDevice, VkFormat format,
169 VkFormatProperties* pFormatProperties) {
170 if (format == VK_FORMAT_B8G8R8A8_UNORM) {
171 pFormatProperties->optimalTilingFeatures =
172 static_cast<VkFormatFeatureFlags>(
173 vk::FormatFeatureFlagBits::eColorAttachment);
174 } else if (format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
175 pFormatProperties->optimalTilingFeatures =
176 static_cast<VkFormatFeatureFlags>(
177 vk::FormatFeatureFlagBits::eDepthStencilAttachment);
178 }
179 // Ignore just the stencil format.
180 })
181 .Build();
182 ASSERT_NE(context, nullptr);
183 const CapabilitiesVK* capabilites_vk =
184 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
185 ASSERT_EQ(capabilites_vk->GetDefaultDepthStencilFormat(),
186 PixelFormat::kD32FloatS8UInt);
187 ASSERT_EQ(capabilites_vk->GetDefaultStencilFormat(),
188 PixelFormat::kD32FloatS8UInt);
189 }

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

## ◆ TEST() [76/370]

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

Definition at line 42 of file command_encoder_vk_unittests.cc.

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

References impeller::CommandBuffer::kCompleted.

## ◆ TEST() [77/370]

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

Definition at line 16 of file command_encoder_vk_unittests.cc.

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

References impeller::CommandEncoderFactoryVK::Create().

## ◆ TEST() [78/370]

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

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

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

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

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

Definition at line 205 of file base_unittests.cc.

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

References impeller::ConditionVariable::Wait().

## ◆ TEST() [83/370]

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

Definition at line 160 of file base_unittests.cc.

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

References impeller::ConditionVariable::WaitFor().

## ◆ TEST() [84/370]

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

Definition at line 122 of file base_unittests.cc.

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

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

## ◆ TEST() [85/370]

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

Definition at line 143 of file base_unittests.cc.

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

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

## ◆ TEST() [86/370]

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

Definition at line 99 of file base_unittests.cc.

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

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

## ◆ TEST() [87/370]

impeller::testing::TEST | ( | ContentContext | ,
|  | CachesPipelines |
| ) |  |

Definition at line 262 of file content_context_unittests.cc.

262 {
263 auto context = std::make_shared<FakeContext>();
264
265 auto create_callback = [&]() {
266 return std::make_shared<FakePipeline>(context->GetPipelineLibrary(),
267 PipelineDescriptor{});
268 };
269
270 ContentContext content_context(context, nullptr);
271 ContentContextOptions optionsA{.blend_mode = BlendMode::kSourceOver};
272 ContentContextOptions optionsB{.blend_mode = BlendMode::kSource};
273
274 auto pipelineA = content_context.GetCachedRuntimeEffectPipeline(
275 "A", optionsA, create_callback);
276
277 auto pipelineA2 = content_context.GetCachedRuntimeEffectPipeline(
278 "A", optionsA, create_callback);
279
280 auto pipelineA3 = content_context.GetCachedRuntimeEffectPipeline(
281 "A", optionsB, create_callback);
282
283 auto pipelineB = content_context.GetCachedRuntimeEffectPipeline(
284 "B", optionsB, create_callback);
285
286 ASSERT_EQ(pipelineA.get(), pipelineA2.get());
287 ASSERT_NE(pipelineA.get(), pipelineA3.get());
288 ASSERT_NE(pipelineB.get(), pipelineA.get());
289 }

References impeller::ContentContextOptions::blend_mode, impeller::ContentContext::GetCachedRuntimeEffectPipeline(), impeller::kSource, and impeller::kSourceOver.

## ◆ TEST() [88/370]

impeller::testing::TEST | ( | ContentContext | ,
|  | InitializeCommonlyUsedShadersIfNeeded |
| ) |  |

Definition at line 337 of file content_context_unittests.cc.

337 {
338 ScopedValidationFatal fatal_validations;
339 // Set a pixel format that is larger than 32bpp.
340 auto context = std::make_shared<FakeContext>("Mali G70",
341 PixelFormat::kR16G16B16A16Float);
342 ContentContext content_context(context, nullptr);
343
344 FakeAllocator& fake_allocator =
345 FakeAllocator::Cast(*context->GetResourceAllocator());
346
347 #if IMPELLER_ENABLE_3D
348 EXPECT_EQ(fake_allocator.textures.size(), 2u);
349 #else
350 EXPECT_EQ(fake_allocator.textures.size(), 1u);
351 #endif // IMPELLER_ENABLE_3D
352 }

References impeller::kR16G16B16A16Float.

## ◆ TEST() [89/370]

impeller::testing::TEST | ( | ContentContext | ,
|  | InvalidatesAllPipelinesWithSameUniqueNameOnClear |
| ) |  |

Definition at line 291 of file content_context_unittests.cc.

291 {
292 auto context = std::make_shared<FakeContext>();
293 ContentContext content_context(context, nullptr);
294 ContentContextOptions optionsA{.blend_mode = BlendMode::kSourceOver};
295 ContentContextOptions optionsB{.blend_mode = BlendMode::kSource};
296
297 auto create_callback = [&]() {
298 return std::make_shared<FakePipeline>(context->GetPipelineLibrary(),
299 PipelineDescriptor{});
300 };
301
302 auto pipelineA = content_context.GetCachedRuntimeEffectPipeline(
303 "A", optionsA, create_callback);
304
305 auto pipelineA2 = content_context.GetCachedRuntimeEffectPipeline(
306 "A", optionsB, create_callback);
307
308 auto pipelineB = content_context.GetCachedRuntimeEffectPipeline(
309 "B", optionsB, create_callback);
310
311 ASSERT_TRUE(pipelineA);
312 ASSERT_TRUE(pipelineA2);
313 ASSERT_TRUE(pipelineB);
314
315 ASSERT_EQ(pipelineA, content_context.GetCachedRuntimeEffectPipeline(
316 "A", optionsA, create_callback));
317 ASSERT_EQ(pipelineA2, content_context.GetCachedRuntimeEffectPipeline(
318 "A", optionsB, create_callback));
319 ASSERT_EQ(pipelineB, content_context.GetCachedRuntimeEffectPipeline(
320 "B", optionsB, create_callback));
321
322 content_context.ClearCachedRuntimeEffectPipeline("A");
323
324 ASSERT_NE(pipelineA, content_context.GetCachedRuntimeEffectPipeline(
325 "A", optionsA, create_callback));
326 ASSERT_NE(pipelineA2, content_context.GetCachedRuntimeEffectPipeline(
327 "A", optionsB, create_callback));
328 ASSERT_EQ(pipelineB, content_context.GetCachedRuntimeEffectPipeline(
329 "B", optionsB, create_callback));
330
331 content_context.ClearCachedRuntimeEffectPipeline("B");
332
333 ASSERT_NE(pipelineB, content_context.GetCachedRuntimeEffectPipeline(
334 "B", optionsB, create_callback));
335 }

References impeller::ContentContextOptions::blend_mode, impeller::ContentContext::ClearCachedRuntimeEffectPipeline(), impeller::ContentContext::GetCachedRuntimeEffectPipeline(), impeller::kSource, and impeller::kSourceOver.

## ◆ TEST() [90/370]

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

Definition at line 132 of file context_vk_unittests.cc.

132 {
133 // The mocked methods don't report the presence of a validation layer but we
134 // explicitly ask for validation. Context creation should continue anyway.
135 auto context = MockVulkanContextBuilder()
136 .SetSettingsCallback([](auto& settings) {
137 settings.enable_validation = true;
138 })
139 .Build();
140 ASSERT_NE(context, nullptr);
141 const CapabilitiesVK* capabilites_vk =
142 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
143 ASSERT_FALSE(capabilites_vk->AreValidationsEnabled());
144 }

References impeller::CapabilitiesVK::AreValidationsEnabled().

## ◆ TEST() [91/370]

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

Definition at line 146 of file context_vk_unittests.cc.

146 {
147 auto context =
148 MockVulkanContextBuilder()
149 .SetSettingsCallback(
150 [](auto& settings) { settings.enable_validation = true; })
151 .SetInstanceExtensions(
152 {"VK_KHR_surface", "VK_MVK_macos_surface", "VK_EXT_debug_utils"})
153 .SetInstanceLayers({"VK_LAYER_KHRONOS_validation"})
154 .Build();
155 ASSERT_NE(context, nullptr);
156 const CapabilitiesVK* capabilites_vk =
157 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
158 ASSERT_TRUE(capabilites_vk->AreValidationsEnabled());
159 }

References impeller::CapabilitiesVK::AreValidationsEnabled().

## ◆ TEST() [92/370]

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

Definition at line 16 of file context_vk_unittests.cc.

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

References impeller::ContextVK::ChooseThreadCountForWorkers().

## ◆ TEST() [93/370]

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

Definition at line 75 of file context_vk_unittests.cc.

75 {
76 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline;
77 std::shared_ptr<std::vector<std::string>> functions;
78 {
79 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
80 PipelineDescriptor pipeline_desc;
81 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
82 PipelineFuture<PipelineDescriptor> pipeline_future =
83 context->GetPipelineLibrary()->GetPipeline(pipeline_desc);
84 pipeline = pipeline_future.Get();
85 ASSERT_TRUE(pipeline);
86 functions = GetMockVulkanFunctions(context->GetDevice());
87 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
88 "vkCreateGraphicsPipelines") != functions->end());
89 }
90 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
91 "vkDestroyDevice") != functions->end());
92 }

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

## ◆ TEST() [94/370]

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

Definition at line 116 of file context_vk_unittests.cc.

116 {
117 std::shared_ptr<PipelineLibrary> pipeline_library;
118 std::shared_ptr<std::vector<std::string>> functions;
119 {
120 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
121 PipelineDescriptor pipeline_desc;
122 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
123 pipeline_library = context->GetPipelineLibrary();
124 functions = GetMockVulkanFunctions(context->GetDevice());
125 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
126 "vkCreatePipelineCache") != functions->end());
127 }
128 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
129 "vkDestroyDevice") != functions->end());
130 }

References impeller::PipelineDescriptor::SetVertexDescriptor().

## ◆ TEST() [95/370]

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

Definition at line 29 of file context_vk_unittests.cc.

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

## ◆ TEST() [96/370]

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

Definition at line 44 of file context_vk_unittests.cc.

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

## ◆ TEST() [97/370]

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

Definition at line 94 of file context_vk_unittests.cc.

94 {
95 std::shared_ptr<const ShaderFunction> shader_function;
96 std::shared_ptr<std::vector<std::string>> functions;
97 {
98 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
99 PipelineDescriptor pipeline_desc;
100 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
101 std::vector<uint8_t> data = {0x03, 0x02, 0x23, 0x07};
102 context->GetShaderLibrary()->RegisterFunction(
103 "foobar_fragment_main", ShaderStage::kFragment,
104 std::make_shared<fml::DataMapping>(data), [](bool) {});
105 shader_function = context->GetShaderLibrary()->GetFunction(
106 "foobar_fragment_main", ShaderStage::kFragment);
107 ASSERT_TRUE(shader_function);
108 functions = GetMockVulkanFunctions(context->GetDevice());
109 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
110 "vkCreateShaderModule") != functions->end());
111 }
112 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
113 "vkDestroyDevice") != functions->end());
114 }

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

## ◆ TEST() [98/370]

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

Definition at line 214 of file context_vk_unittests.cc.

214 {
215 const std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
216
217 context->SetOffscreenFormat(PixelFormat::kR8G8B8A8UNormInt);
218 context->InitializeCommonlyUsedShadersIfNeeded();
219
220 auto functions = GetMockVulkanFunctions(context->GetDevice());
221 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
222 "vkCreateRenderPass") != functions->end());
223 }

References impeller::kR8G8B8A8UNormInt.

## ◆ TEST() [99/370]

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

Definition at line 14 of file descriptor_pool_vk_unittests.cc.

14 {
15 auto const context = MockVulkanContextBuilder().Build();
16
17 auto const pool1 = context->GetDescriptorPoolRecycler()->Get();
18 auto const pool2 = context->GetDescriptorPoolRecycler()->Get();
19
20 // The two descriptor pools should be different.
21 EXPECT_NE(pool1.get(), pool2.get());
22
23 context->Shutdown();
24 }

## ◆ TEST() [100/370]

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

Definition at line 85 of file descriptor_pool_vk_unittests.cc.

85 {
86 auto const context = MockVulkanContextBuilder().Build();
87
88 // Create 33 pools
89 {
90 std::vector<std::unique_ptr<DescriptorPoolVK>> pools;
91 for (auto i = 0u; i < 33; i++) {
92 auto pool = std::make_unique<DescriptorPoolVK>(context);
93 pool->AllocateDescriptorSets({}, *context);
94 pools.push_back(std::move(pool));
95 }
96 }
97
98 // See note above.
99 for (auto i = 0u; i < 2; i++) {
100 auto waiter = fml::AutoResetWaitableEvent();
101 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
102 {
103 UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
104 std::move(rattle));
105 }
106 waiter.Wait();
107 }
108
109 auto const called = GetMockVulkanFunctions(context->GetDevice());
110 EXPECT_EQ(
111 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
112 33u);
113 EXPECT_EQ(std::count(called->begin(), called->end(), "vkResetDescriptorPool"),
114 33u);
115
116 // Now create 33 more descriptor pools and observe that only one more is
117 // allocated.
118 {
119 std::vector<std::unique_ptr<DescriptorPoolVK>> pools;
120 for (auto i = 0u; i < 33; i++) {
121 auto pool = std::make_unique<DescriptorPoolVK>(context);
122 pool->AllocateDescriptorSets({}, *context);
123 pools.push_back(std::move(pool));
124 }
125 }
126
127 for (auto i = 0u; i < 2; i++) {
128 auto waiter = fml::AutoResetWaitableEvent();
129 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
130 {
131 UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
132 std::move(rattle));
133 }
134 waiter.Wait();
135 }
136
137 auto const called_twice = GetMockVulkanFunctions(context->GetDevice());
138 // 32 of the descriptor pools were recycled, so only one more is created.
139 EXPECT_EQ(
140 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
141 34u);
142
143 context->Shutdown();
144 }

## ◆ TEST() [101/370]

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

Definition at line 47 of file descriptor_pool_vk_unittests.cc.

47 {
48 auto const context = MockVulkanContextBuilder().Build();
49
50 {
51 // Fetch a pool (which will be created).
52 auto pool = DescriptorPoolVK(context);
53 pool.AllocateDescriptorSets({}, *context);
54 }
55
56 // There is a chance that the first death rattle item below is destroyed in
57 // the same reclaim cycle as the pool allocation above. These items are placed
58 // into a std::vector and free'd, which may free in reverse order. That would
59 // imply that the death rattle and subsequent waitable event fires before the
60 // pool is reset. To work around this, we can either manually remove items
61 // from the vector or use two death rattles.
62 for (auto i = 0u; i < 2; i++) {
63 // Add something to the resource manager and have it notify us when it's
64 // destroyed. That should give us a non-flaky signal that the pool has been
65 // reclaimed as well.
66 auto waiter = fml::AutoResetWaitableEvent();
67 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
68 {
69 UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
70 std::move(rattle));
71 }
72 waiter.Wait();
73 }
74
75 auto const pool = context->GetDescriptorPoolRecycler()->Get();
76
77 // Now check that we only ever created one pool.
78 auto const called = GetMockVulkanFunctions(context->GetDevice());
79 EXPECT_EQ(
80 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"), 1u);
81
82 context->Shutdown();
83 }

## ◆ TEST() [102/370]

impeller::testing::TEST | ( | DisplayListTest | ,
|  | CircleBoundsComputation |
| ) |  |

Definition at line 1789 of file dl_unittests.cc.

1789 {
1790 SkPath path = SkPath().addCircle(0, 0, 5);
1791
1792 flutter::DlPaint paint;
1793 flutter::DisplayListBuilder builder;
1794
1795 builder.DrawPath(path, paint);
1796 auto display_list = builder.Build();
1797
1798 DlDispatcher dispatcher;
1799 display_list->Dispatch(dispatcher);
1800 auto picture = dispatcher.EndRecordingAsPicture();
1801
1802 std::optional<Rect> coverage =
1803 GetCoverageOfFirstEntity<SolidColorContents>(picture);
1804
1805 ASSERT_TRUE(coverage.has_value());
1806 ASSERT_EQ(coverage.value_or(Rect::MakeMaximum()),
1807 Rect::MakeLTRB(-5, -5, 5, 5));
1808 }

References impeller::DlDispatcher::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeMaximum().

## ◆ TEST() [103/370]

impeller::testing::TEST | ( | DisplayListTest | ,
|  | RRectBoundsComputation |
| ) |  |

Definition at line 1766 of file dl_unittests.cc.

1766 {
1767 SkRRect rrect = SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 100, 100), 4, 4);
1768 SkPath path = SkPath().addRRect(rrect);
1769
1770 flutter::DlPaint paint;
1771 flutter::DisplayListBuilder builder;
1772
1773 builder.DrawPath(path, paint);
1774 auto display_list = builder.Build();
1775
1776 DlDispatcher dispatcher;
1777 display_list->Dispatch(dispatcher);
1778 auto picture = dispatcher.EndRecordingAsPicture();
1779
1780 std::optional<Rect> coverage =
1781 GetCoverageOfFirstEntity<SolidColorContents>(picture);
1782
1783 // Validate that the RRect coverage is _exactly_ the same as the input rect.
1784 ASSERT_TRUE(coverage.has_value());
1785 ASSERT_EQ(coverage.value_or(Rect::MakeMaximum()),
1786 Rect::MakeLTRB(0, 0, 100, 100));
1787 }

References impeller::DlDispatcher::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeMaximum().

## ◆ TEST() [104/370]

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

Definition at line 91 of file geometry_unittests.cc.

91 {
92 auto path = PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath();
93 auto geometry = Geometry::MakeFillPath(
94 path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
95 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
96 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
97 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
98 ASSERT_TRUE(geometry->CoversArea({}, Rect()));
99 }

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

## ◆ TEST() [105/370]

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

Definition at line 101 of file geometry_unittests.cc.

101 {
102 auto path = PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath();
103 auto geometry = Geometry::MakeFillPath(path);
104 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
105 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
106 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
107 ASSERT_FALSE(geometry->CoversArea({}, Rect()));
108 }

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

## ◆ TEST() [106/370]

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

Definition at line 234 of file geometry_unittests.cc.

234 {
235 GeometryResult result;
236 EXPECT_EQ(result.type, PrimitiveType::kTriangleStrip);
237 EXPECT_EQ(result.transform, Matrix());
238 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
239 }

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

## ◆ TEST() [107/370]

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

Definition at line 110 of file geometry_unittests.cc.

110 {
111 {
112 auto geometry = Geometry::MakeLine({10, 10}, {20, 10}, 2, Cap::kButt);
113 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(10, 9, 20, 11));
114 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(10, 9, 20, 11)));
115 }
116
117 {
118 auto geometry = Geometry::MakeLine({10, 10}, {20, 10}, 2, Cap::kSquare);
119 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 9, 21, 11));
120 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 9, 21, 11)));
121 }
122
123 {
124 auto geometry = Geometry::MakeLine({10, 10}, {10, 20}, 2, Cap::kButt);
125 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 10, 11, 20));
126 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 10, 11, 20)));
127 }
128
129 {
130 auto geometry = Geometry::MakeLine({10, 10}, {10, 20}, 2, Cap::kSquare);
131 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 9, 11, 21));
132 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 9, 11, 21)));
133 }
134 }

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

## ◆ TEST() [108/370]

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

Definition at line 83 of file geometry_unittests.cc.

83 {
84 auto geometry = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 100, 100));
85 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
86 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
87 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
88 ASSERT_TRUE(geometry->CoversArea({}, Rect()));
89 }

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

## ◆ TEST() [109/370]

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

Definition at line 136 of file geometry_unittests.cc.

136 {
137 auto geometry =
138 Geometry::MakeRoundRect(Rect::MakeLTRB(0, 0, 100, 100), Size(20, 20));
139 EXPECT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(15, 15, 85, 85)));
140 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(20, 20, 80, 80)));
141 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(30, 1, 70, 99)));
142 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 30, 99, 70)));
143 }

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

## ◆ TEST() [110/370]

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

Definition at line 145 of file geometry_unittests.cc.

145 {
146 auto path =
147 PathBuilder().AddLine(Point(100, 100), Point(200, 100)).TakePath();
148 auto points = std::make_unique<std::vector<Point>>();
149 auto polyline =
150 path.CreatePolyline(1.0f, std::move(points),
151 [&points](Path::Polyline::PointBufferPtr reclaimed) {
152 points = std::move(reclaimed);
153 });
154
155 auto vertices = ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
156 polyline, 10.0f, 10.0f, Join::kBevel, Cap::kButt, 1.0);
157
158 std::vector<SolidFillVertexShader::PerVertexData> expected = {
159 {.position = Point(100.0f, 105.0f)}, //
160 {.position = Point(100.0f, 95.0f)}, //
161 {.position = Point(100.0f, 105.0f)}, //
162 {.position = Point(100.0f, 95.0f)}, //
163 {.position = Point(200.0f, 105.0f)}, //
164 {.position = Point(200.0f, 95.0f)}, //
165 {.position = Point(200.0f, 105.0f)}, //
166 {.position = Point(200.0f, 95.0f)}, //
167 };
168
169 EXPECT_SOLID_VERTICES_NEAR(vertices, expected);
170
171 {
172 auto uv_vertices =
173 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVerticesUV(
174 polyline, 10.0f, 10.0f, Join::kBevel, Cap::kButt, 1.0, //
175 Point(50.0f, 40.0f), Size(20.0f, 40.0f), Matrix());
176 // uvx = (x - 50) / 20
177 // uvy = (y - 40) / 40
178 auto uv = [](const Point& p) {
179 return Point((p.x - 50.0f) / 20.0f, //
180 (p.y - 40.0f) / 40.0f);
181 };
182 std::vector<TextureFillVertexShader::PerVertexData> uv_expected;
183 for (size_t i = 0; i < expected.size(); i++) {
184 auto p = expected[i].position;
185 uv_expected.push_back({.position = p, .texture_coords = uv(p)});
186 }
187
188 EXPECT_TEXTURE_VERTICES_NEAR(uv_vertices, uv_expected);
189 }
190
191 {
192 auto uv_vertices =
193 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVerticesUV(
194 polyline, 10.0f, 10.0f, Join::kBevel, Cap::kButt, 1.0, //
195 Point(50.0f, 40.0f), Size(20.0f, 40.0f),
196 Matrix::MakeScale({8.0f, 4.0f, 1.0f}));
197 // uvx = ((x * 8) - 50) / 20
198 // uvy = ((y * 4) - 40) / 40
199 auto uv = [](const Point& p) {
200 return Point(((p.x * 8.0f) - 50.0f) / 20.0f,
201 ((p.y * 4.0f) - 40.0f) / 40.0f);
202 };
203 std::vector<TextureFillVertexShader::PerVertexData> uv_expected;
204 for (size_t i = 0; i < expected.size(); i++) {
205 auto p = expected[i].position;
206 uv_expected.push_back({.position = p, .texture_coords = uv(p)});
207 }
208
209 EXPECT_TEXTURE_VERTICES_NEAR(uv_vertices, uv_expected);
210 }
211
212 {
213 auto uv_vertices =
214 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVerticesUV(
215 polyline, 10.0f, 10.0f, Join::kBevel, Cap::kButt, 1.0, //
216 Point(50.0f, 40.0f), Size(20.0f, 40.0f),
217 Matrix::MakeTranslation({8.0f, 4.0f}));
218 // uvx = ((x + 8) - 50) / 20
219 // uvy = ((y + 4) - 40) / 40
220 auto uv = [](const Point& p) {
221 return Point(((p.x + 8.0f) - 50.0f) / 20.0f,
222 ((p.y + 4.0f) - 40.0f) / 40.0f);
223 };
224 std::vector<TextureFillVertexShader::PerVertexData> uv_expected;
225 for (size_t i = 0; i < expected.size(); i++) {
226 auto p = expected[i].position;
227 uv_expected.push_back({.position = p, .texture_coords = uv(p)});
228 }
229
230 EXPECT_TEXTURE_VERTICES_NEAR(uv_vertices, uv_expected);
231 }
232 }

References impeller::PathBuilder::AddLine(), EXPECT_SOLID_VERTICES_NEAR, EXPECT_TEXTURE_VERTICES_NEAR, impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVerticesUV(), impeller::kBevel, impeller::kButt, impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), polyline, and impeller::PathBuilder::TakePath().

## ◆ TEST() [111/370]

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

Definition at line 89 of file entity_pass_unittests.cc.

89 {
90 EntityPassClipStack recorder =
91 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
92
93 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
94
95 // Push a clip.
96 Entity entity;
97 entity.SetClipDepth(0);
98 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
99 Contents::ClipCoverage{
100 .type = Contents::ClipCoverage::Type::kAppend,
101 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
102 },
103 entity, 0, Point(0, 0));
104 EXPECT_TRUE(result.should_render);
105 EXPECT_TRUE(result.clip_did_change);
106
107 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
108 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
109 Rect::MakeLTRB(50, 50, 55, 55));
110 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_depth, 1u);
111 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
112
113 // Restore the clip.
114 entity.SetClipDepth(0);
115 recorder.ApplyClipState(
116 Contents::ClipCoverage{
117 .type = Contents::ClipCoverage::Type::kRestore,
118 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
119 },
120 entity, 0, Point(0, 0));
121
122 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
123 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
124 Rect::MakeSize(Size::MakeWH(100, 100)));
125 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_depth, 0u);
126 EXPECT_EQ(recorder.GetReplayEntities().size(), 0u);
127 }

References impeller::EntityPassClipStack::ApplyClipState(), impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::Contents::ClipCoverage::kAppend, impeller::Contents::ClipCoverage::kRestore, impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TSize< Scalar >::MakeWH(), impeller::Entity::SetClipDepth(), impeller::EntityPassClipStack::ClipStateResult::should_render, and impeller::Contents::ClipCoverage::type.

## ◆ TEST() [112/370]

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

Definition at line 66 of file entity_pass_unittests.cc.

66 {
67 EntityPassClipStack recorder =
68 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
69
70 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
71 Rect::MakeSize(Size::MakeWH(100, 100)));
72 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_depth, 0u);
73
74 Entity entity;
75 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
76 Contents::ClipCoverage{
77 .type = Contents::ClipCoverage::Type::kNoChange,
78 .coverage = std::nullopt,
79 },
80 entity, 0, Point(0, 0));
81 EXPECT_TRUE(result.should_render);
82 EXPECT_FALSE(result.clip_did_change);
83
84 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
85 Rect::MakeSize(Size::MakeWH(100, 100)));
86 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_depth, 0u);
87 }

References impeller::EntityPassClipStack::ApplyClipState(), impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::Contents::ClipCoverage::kNoChange, impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TSize< Scalar >::MakeWH(), impeller::EntityPassClipStack::ClipStateResult::should_render, and impeller::Contents::ClipCoverage::type.

## ◆ TEST() [113/370]

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

Definition at line 54 of file entity_pass_unittests.cc.

54 {
55 EntityPassClipStack recorder =
56 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
57
58 EXPECT_TRUE(recorder.GetReplayEntities().empty());
59
60 Entity entity;
61 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kNoChange,
62 Rect());
63 EXPECT_TRUE(recorder.GetReplayEntities().empty());
64 }

References impeller::EntityPassClipStack::GetReplayEntities(), impeller::Contents::ClipCoverage::kNoChange, impeller::TRect< Scalar >::MakeLTRB(), and impeller::EntityPassClipStack::RecordEntity().

## ◆ TEST() [114/370]

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

Definition at line 43 of file entity_pass_unittests.cc.

43 {
44 EntityPassClipStack recorder =
45 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
46
47 EXPECT_TRUE(recorder.GetReplayEntities().empty());
48
49 Entity entity;
50 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kRestore, Rect());
51 EXPECT_TRUE(recorder.GetReplayEntities().empty());
52 }

References impeller::EntityPassClipStack::GetReplayEntities(), impeller::Contents::ClipCoverage::kRestore, impeller::TRect< Scalar >::MakeLTRB(), and impeller::EntityPassClipStack::RecordEntity().

## ◆ TEST() [115/370]

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

Definition at line 13 of file entity_pass_unittests.cc.

13 {
14 EntityPassClipStack recorder =
15 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
16
17 EXPECT_TRUE(recorder.GetReplayEntities().empty());
18
19 Entity entity;
20 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kAppend,
21 Rect::MakeLTRB(0, 0, 100, 100));
22 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
23
24 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kAppend,
25 Rect::MakeLTRB(0, 0, 50, 50));
26 EXPECT_EQ(recorder.GetReplayEntities().size(), 2u);
27 ASSERT_TRUE(recorder.GetReplayEntities()[0].clip_coverage.has_value());
28 ASSERT_TRUE(recorder.GetReplayEntities()[1].clip_coverage.has_value());
29 // NOLINTBEGIN(bugprone-unchecked-optional-access)
30 EXPECT_EQ(recorder.GetReplayEntities()[0].clip_coverage.value(),
31 Rect::MakeLTRB(0, 0, 100, 100));
32 EXPECT_EQ(recorder.GetReplayEntities()[1].clip_coverage.value(),
33 Rect::MakeLTRB(0, 0, 50, 50));
34 // NOLINTEND(bugprone-unchecked-optional-access)
35
36 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kRestore, Rect());
37 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
38
39 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kRestore, Rect());
40 EXPECT_TRUE(recorder.GetReplayEntities().empty());
41 }

References impeller::EntityPassClipStack::GetReplayEntities(), impeller::Contents::ClipCoverage::kAppend, impeller::Contents::ClipCoverage::kRestore, impeller::TRect< Scalar >::MakeLTRB(), and impeller::EntityPassClipStack::RecordEntity().

## ◆ TEST() [116/370]

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

Definition at line 154 of file entity_pass_unittests.cc.

154 {
155 EntityPassClipStack recorder =
156 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
157
158 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
159
160 // Push a clip.
161 Entity entity;
162 entity.SetClipDepth(0u);
163 {
164 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
165 Contents::ClipCoverage{
166 .type = Contents::ClipCoverage::Type::kAppend,
167 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
168 },
169 entity, 0, Point(0, 0));
170 EXPECT_TRUE(result.should_render);
171 EXPECT_TRUE(result.clip_did_change);
172 }
173
174 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
175 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
176 Rect::MakeLTRB(50, 50, 55, 55));
177 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_depth, 1u);
178 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
179
180 // Begin a subpass.
181 recorder.PushSubpass(Rect::MakeLTRB(50, 50, 55, 55), 1);
182 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
183 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
184 Rect::MakeLTRB(50, 50, 55, 55));
185
186 entity.SetClipDepth(1);
187 {
188 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
189 Contents::ClipCoverage{
190 .type = Contents::ClipCoverage::Type::kAppend,
191 .coverage = Rect::MakeLTRB(54, 54, 55, 55),
192 },
193 entity, 0, Point(0, 0));
194 EXPECT_TRUE(result.should_render);
195 EXPECT_TRUE(result.clip_did_change);
196 }
197
198 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
199 Rect::MakeLTRB(54, 54, 55, 55));
200
201 // End subpass.
202 recorder.PopSubpass();
203
204 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
205 Rect::MakeLTRB(50, 50, 55, 55));
206 }

References impeller::EntityPassClipStack::ApplyClipState(), impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::Contents::ClipCoverage::kAppend, impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::PopSubpass(), impeller::EntityPassClipStack::PushSubpass(), impeller::Entity::SetClipDepth(), impeller::EntityPassClipStack::ClipStateResult::should_render, and impeller::Contents::ClipCoverage::type.

## ◆ TEST() [117/370]

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

Definition at line 129 of file entity_pass_unittests.cc.

129 {
130 EntityPassClipStack recorder =
131 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
132
133 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
134
135 // Restore the clip.
136 Entity entity;
137 entity.SetClipDepth(0);
138 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
139 Contents::ClipCoverage{
140 .type = Contents::ClipCoverage::Type::kRestore,
141 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
142 },
143 entity, 0, Point(0, 0));
144 EXPECT_FALSE(result.should_render);
145 EXPECT_FALSE(result.clip_did_change);
146
147 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
148 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
149 Rect::MakeSize(Size::MakeWH(100, 100)));
150 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_depth, 0u);
151 EXPECT_EQ(recorder.GetReplayEntities().size(), 0u);
152 }

References impeller::EntityPassClipStack::ApplyClipState(), impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::Contents::ClipCoverage::kRestore, impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TSize< Scalar >::MakeWH(), impeller::Entity::SetClipDepth(), impeller::EntityPassClipStack::ClipStateResult::should_render, and impeller::Contents::ClipCoverage::type.

## ◆ TEST() [118/370]

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 }

## ◆ TEST() [119/370]

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 }

## ◆ TEST() [120/370]

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 }

## ◆ TEST() [121/370]

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 }

## ◆ TEST() [122/370]

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 }

## ◆ TEST() [123/370]

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

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 }

## ◆ TEST() [125/370]

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

Definition at line 17 of file filter_input_unittests.cc.

17 {
18 std::shared_ptr<Texture> texture = nullptr;
19 auto input =
20 FilterInput::Make(texture, Matrix::MakeTranslation({1.0, 0.0, 0.0}));
21 Entity e;
22 e.SetTransform(Matrix::MakeTranslation({0.0, 2.0, 0.0}));
23
24 ASSERT_MATRIX_NEAR(input->GetLocalTransform(e),
25 Matrix::MakeTranslation({1.0, 0.0, 0.0}));
26 ASSERT_MATRIX_NEAR(input->GetTransform(e),
27 Matrix::MakeTranslation({1.0, 2.0, 0.0}));
28 }

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

## ◆ TEST() [126/370]

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

Definition at line 30 of file filter_input_unittests.cc.

30 {
31 std::shared_ptr<FilterContents> leaf =
32 ColorFilterContents::MakeBlend(BlendMode::kSource, {});
33 ASSERT_TRUE(leaf->IsLeaf());
34
35 auto base = ColorFilterContents::MakeMatrixFilter(FilterInput::Make(leaf),
36 Matrix(), {});
37
38 ASSERT_TRUE(leaf->IsLeaf());
39 ASSERT_FALSE(base->IsLeaf());
40 }

References impeller::kSource, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), and impeller::FilterContents::MakeMatrixFilter().

## ◆ TEST() [127/370]

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

Definition at line 42 of file filter_input_unittests.cc.

42 {
43 std::shared_ptr<FilterContents> leaf =
44 ColorFilterContents::MakeBlend(BlendMode::kSource, {});
45 ASSERT_TRUE(leaf->IsLeaf());
46
47 auto base = ColorFilterContents::MakeMatrixFilter(FilterInput::Make(leaf),
48 Matrix(), {});
49
50 {
51 auto result = base->GetCoverage({});
52 ASSERT_FALSE(result.has_value());
53 }
54
55 auto coverage_rect = Rect::MakeLTRB(100, 100, 200, 200);
56 base->SetLeafInputs(FilterInput::Make({coverage_rect}));
57
58 {
59 auto result = base->GetCoverage({});
60 ASSERT_TRUE(result.has_value());
61 // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
62 ASSERT_RECT_NEAR(result.value(), coverage_rect);
63 }
64 }

References ASSERT_RECT_NEAR, impeller::kSource, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::FilterContents::MakeMatrixFilter().

## ◆ TEST() [128/370]

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

Definition at line 429 of file gaussian_blur_filter_contents_unittests.cc.

429 {
430 Scalar sigma = 1.0;
431 Scalar radius = GaussianBlurFilterContents::CalculateBlurRadius(
432 GaussianBlurFilterContents::ScaleSigma(sigma));
433 fml::StatusOr<Scalar> derived_sigma =
434 CalculateSigmaForBlurRadius(radius, Matrix());
435 ASSERT_TRUE(derived_sigma.ok());
436 EXPECT_NEAR(sigma, derived_sigma.value(), 0.01f);
437 }

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

## ◆ TEST() [129/370]

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

Definition at line 200 of file gaussian_blur_filter_contents_unittests.cc.

200 {
201 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1.0f), 1);
202 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(2.0f), 1);
203 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(3.0f), 1);
204 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(4.0f), 1);
205 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(16.0f), 0.25);
206 // Hang on to 1/8 as long as possible.
207 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(95.0f), 0.125);
208 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(96.0f), 0.0625);
209 // Downsample clamped to 1/16th.
210 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1024.0f), 0.0625);
211 }

References impeller::GaussianBlurFilterContents::CalculateScale().

## ◆ TEST() [130/370]

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

Definition at line 439 of file gaussian_blur_filter_contents_unittests.cc.

439 {
440 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
441 .blur_sigma = 1,
442 .blur_radius = 5,
443 .step_size = 1};
444 KernelPipeline::FragmentShader::KernelSamples samples =
445 GenerateBlurInfo(parameters);
446 EXPECT_EQ(samples.sample_count, 9);
447
448 // Coefficients should add up to 1.
449 Scalar tally = 0;
450 for (int i = 0; i < samples.sample_count; ++i) {
451 tally += samples.samples[i].coefficient;
452 }
453 EXPECT_FLOAT_EQ(tally, 1.0f);
454
455 // Verify the shape of the curve.
456 for (int i = 0; i < 4; ++i) {
457 EXPECT_FLOAT_EQ(samples.samples[i].coefficient,
458 samples.samples[8 - i].coefficient);
459 EXPECT_TRUE(samples.samples[i + 1].coefficient >
460 samples.samples[i].coefficient);
461 }
462 }

References impeller::BlurParameters::blur_uv_offset, and impeller::GenerateBlurInfo().

## ◆ TEST() [131/370]

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

Definition at line 96 of file gaussian_blur_filter_contents_unittests.cc.

96 {
97 GaussianBlurFilterContents contents(
98 /*sigma_x=*/0.0, /*sigma_y=*/0.0, Entity::TileMode::kDecal,
99 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
100 FilterInput::Vector inputs = {};
101 Entity entity;
102 std::optional<Rect> coverage =
103 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
104 ASSERT_FALSE(coverage.has_value());
105 }

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

## ◆ TEST() [132/370]

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

Definition at line 107 of file gaussian_blur_filter_contents_unittests.cc.

107 {
108 GaussianBlurFilterContents contents(
109 /*sigma_x=*/0.0, /*sigma_y=*/0.0, Entity::TileMode::kDecal,
110 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
111 FilterInput::Vector inputs = {
112 FilterInput::Make(Rect::MakeLTRB(10, 10, 110, 110))};
113 Entity entity;
114 std::optional<Rect> coverage =
115 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
116
117 ASSERT_EQ(coverage, Rect::MakeLTRB(10, 10, 110, 110));
118 }

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

## ◆ TEST() [133/370]

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

Definition at line 120 of file gaussian_blur_filter_contents_unittests.cc.

120 {
121 fml::StatusOr<Scalar> sigma_radius_1 =
122 CalculateSigmaForBlurRadius(1.0, Matrix());
123 ASSERT_TRUE(sigma_radius_1.ok());
124 GaussianBlurFilterContents contents(
125 /*sigma_x=*/sigma_radius_1.value(),
126 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
127 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
128 FilterInput::Vector inputs = {
129 FilterInput::Make(Rect::MakeLTRB(100, 100, 200, 200))};
130 Entity entity;
131 std::optional<Rect> coverage =
132 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
133
134 EXPECT_TRUE(coverage.has_value());
135 if (coverage.has_value()) {
136 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(99, 99, 201, 201));
137 }
138 }

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

## ◆ TEST() [134/370]

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

Definition at line 88 of file gaussian_blur_filter_contents_unittests.cc.

88 {
89 GaussianBlurFilterContents contents(
90 /*sigma_x=*/0.0, /*sigma_y=*/0.0, Entity::TileMode::kDecal,
91 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
92 EXPECT_EQ(contents.GetSigmaX(), 0.0);
93 EXPECT_EQ(contents.GetSigmaY(), 0.0);
94 }

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

## ◆ TEST() [135/370]

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

Definition at line 183 of file gaussian_blur_filter_contents_unittests.cc.

183 {
184 fml::StatusOr<Scalar> sigma_radius_1 =
185 CalculateSigmaForBlurRadius(1.0, Matrix());
186 ASSERT_TRUE(sigma_radius_1.ok());
187 auto contents = std::make_unique<GaussianBlurFilterContents>(
188 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
189 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
190 std::optional<Rect> coverage = contents->GetFilterSourceCoverage(
191 /*effect_transform=*/Matrix::MakeScale({2.0, 2.0, 1.0}),
192 /*output_limit=*/Rect::MakeLTRB(100, 100, 200, 200));
193 EXPECT_TRUE(coverage.has_value());
194 if (coverage.has_value()) {
195 EXPECT_RECT_NEAR(coverage.value(),
196 Rect::MakeLTRB(100 - 2, 100 - 2, 200 + 2, 200 + 2));
197 }
198 }

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

## ◆ TEST() [136/370]

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

Definition at line 542 of file gaussian_blur_filter_contents_unittests.cc.

542 {
543 Scalar sigma = 10.0f;
544 int32_t blur_radius = static_cast<int32_t>(
545 std::ceil(GaussianBlurFilterContents::CalculateBlurRadius(sigma)));
546 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
547 .blur_sigma = sigma,
548 .blur_radius = blur_radius,
549 .step_size = 1};
550 KernelPipeline::FragmentShader::KernelSamples kernel_samples =
551 GenerateBlurInfo(parameters);
552 EXPECT_EQ(kernel_samples.sample_count, 33);
553 KernelPipeline::FragmentShader::KernelSamples fast_kernel_samples =
554 LerpHackKernelSamples(kernel_samples);
555 EXPECT_EQ(fast_kernel_samples.sample_count, 17);
556 float data[33];
557 srand(0);
558 for (int i = 0; i < 33; i++) {
559 data[i] = 255.0 * static_cast<double>(IMPELLER_RAND()) / RAND_MAX;
560 }
561
562 auto sampler = [data](Point point) -> Scalar {
563 FML_CHECK(point.y == 0.0f);
564 FML_CHECK(point.x >= -16);
565 FML_CHECK(point.x <= 16);
566 Scalar fint_part;
567 Scalar fract = fabsf(modf(point.x, &fint_part));
568 if (fract == 0) {
569 int32_t int_part = static_cast<int32_t>(fint_part) + 16;
570 return data[int_part];
571 } else {
572 int32_t left = static_cast<int32_t>(floor(point.x)) + 16;
573 int32_t right = static_cast<int32_t>(ceil(point.x)) + 16;
574 if (point.x < 0) {
575 return fract * data[left] + (1.0 - fract) * data[right];
576 } else {
577 return (1.0 - fract) * data[left] + fract * data[right];
578 }
579 }
580 };
581
582 Scalar output = 0.0;
583 for (int i = 0; i < kernel_samples.sample_count; ++i) {
584 auto sample = kernel_samples.samples[i];
585 output += sample.coefficient * sampler(sample.uv_offset);
586 }
587
588 Scalar fast_output = 0.0;
589 for (int i = 0; i < fast_kernel_samples.sample_count; ++i) {
590 auto sample = fast_kernel_samples.samples[i];
591 fast_output += sample.coefficient * sampler(sample.uv_offset);
592 }
593
594 EXPECT_NEAR(output, fast_output, 0.1);
595 }

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

## ◆ TEST() [137/370]

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

Definition at line 464 of file gaussian_blur_filter_contents_unittests.cc.

464 {
465 KernelPipeline::FragmentShader::KernelSamples kernel_samples = {
466 .sample_count = 5,
467 .samples =
468 {
469 {
470 .uv_offset = Vector2(-2, 0),
471 .coefficient = 0.1f,
472 },
473 {
474 .uv_offset = Vector2(-1, 0),
475 .coefficient = 0.2f,
476 },
477 {
478 .uv_offset = Vector2(0, 0),
479 .coefficient = 0.4f,
480 },
481 {
482 .uv_offset = Vector2(1, 0),
483 .coefficient = 0.2f,
484 },
485 {
486 .uv_offset = Vector2(2, 0),
487 .coefficient = 0.1f,
488 },
489 },
490 };
491
492 KernelPipeline::FragmentShader::KernelSamples fast_kernel_samples =
493 LerpHackKernelSamples(kernel_samples);
494 EXPECT_EQ(fast_kernel_samples.sample_count, 3);
495
496 KernelPipeline::FragmentShader::KernelSample* samples =
497 kernel_samples.samples;
498 KernelPipeline::FragmentShader::KernelSample* fast_samples =
499 fast_kernel_samples.samples;
500
501 //////////////////////////////////////////////////////////////////////////////
502 // Check output kernel.
503
504 EXPECT_FLOAT_EQ(fast_samples[0].uv_offset.x, -1.3333333);
505 EXPECT_FLOAT_EQ(fast_samples[0].uv_offset.y, 0);
506 EXPECT_FLOAT_EQ(fast_samples[0].coefficient, 0.3);
507 EXPECT_FLOAT_EQ(fast_samples[1].uv_offset.x, 0);
508 EXPECT_FLOAT_EQ(fast_samples[1].uv_offset.y, 0);
509 EXPECT_FLOAT_EQ(fast_samples[1].coefficient, 0.4);
510 EXPECT_FLOAT_EQ(fast_samples[2].uv_offset.x, 1.3333333);
511 EXPECT_FLOAT_EQ(fast_samples[2].uv_offset.y, 0);
512 EXPECT_FLOAT_EQ(fast_samples[2].coefficient, 0.3);
513
514 //////////////////////////////////////////////////////////////////////////////
515 // Check output of fast kernel versus original kernel.
516
517 Scalar data[5] = {0.25, 0.5, 0.5, 1.0, 0.2};
518 Scalar original_output =
519 samples[0].coefficient * data[0] + samples[1].coefficient * data[1] +
520 samples[2].coefficient * data[2] + samples[3].coefficient * data[3] +
521 samples[4].coefficient * data[4];
522
523 auto lerp = [](const Point& point, Scalar left, Scalar right) {
524 Scalar int_part;
525 Scalar fract = fabsf(modf(point.x, &int_part));
526 if (point.x < 0) {
527 return left * fract + right * (1.0 - fract);
528 } else {
529 return left * (1.0 - fract) + right * fract;
530 }
531 };
532 Scalar fast_output =
533 /*1st*/ lerp(fast_samples[0].uv_offset, data[0], data[1]) *
534 fast_samples[0].coefficient +
535 /*2nd*/ data[2] * fast_samples[1].coefficient +
536 /*3rd*/ lerp(fast_samples[2].uv_offset, data[3], data[4]) *
537 fast_samples[2].coefficient;
538
539 EXPECT_NEAR(original_output, fast_output, 0.01);
540 }

References impeller::LerpHackKernelSamples(), and impeller::TPoint< T >::x.

## ◆ TEST() [138/370]

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

Definition at line 1603 of file geometry_unittests.cc.

1603 {
1604 using BlendT = std::underlying_type_t<BlendMode>;
1605 for (BlendT i = 0; i <= static_cast<BlendT>(BlendMode::kLast); i++) {
1606 auto mode = static_cast<BlendMode>(i);
1607 auto result = BlendModeToString(mode);
1608 switch (mode) { IMPELLER_FOR_EACH_BLEND_MODE(_BLEND_MODE_NAME_CHECK) }
1609 }
1610 }

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

## ◆ TEST() [139/370]

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

Definition at line 1612 of file geometry_unittests.cc.

1612 {
1613 {
1614 auto deg = Degrees{90.0};
1615 Radians rad = deg;
1616 ASSERT_FLOAT_EQ(rad.radians, kPiOver2);
1617 }
1618 }

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

## ◆ TEST() [140/370]

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

Definition at line 616 of file geometry_unittests.cc.

616 {
617 {
618 Point p1(1.0, 2.0);
619 IPoint p2 = static_cast<IPoint>(p1);
620 ASSERT_EQ(p2.x, 1u);
621 ASSERT_EQ(p2.y, 2u);
622 }
623
624 {
625 Size s1(1.0, 2.0);
626 ISize s2 = static_cast<ISize>(s1);
627 ASSERT_EQ(s2.width, 1u);
628 ASSERT_EQ(s2.height, 2u);
629 }
630
631 {
632 Size s1(1.0, 2.0);
633 Point p1 = static_cast<Point>(s1);
634 ASSERT_EQ(p1.x, 1u);
635 ASSERT_EQ(p1.y, 2u);
636 }
637 }

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

## ◆ TEST() [141/370]

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

Definition at line 603 of file geometry_unittests.cc.

603 {
604 ASSERT_EQ((Size{128, 128}.MipCount()), 7u);
605 ASSERT_EQ((Size{128, 256}.MipCount()), 8u);
606 ASSERT_EQ((Size{128, 130}.MipCount()), 8u);
607 ASSERT_EQ((Size{128, 257}.MipCount()), 9u);
608 ASSERT_EQ((Size{257, 128}.MipCount()), 9u);
609 ASSERT_EQ((Size{128, 0}.MipCount()), 1u);
610 ASSERT_EQ((Size{128, -25}.MipCount()), 1u);
611 ASSERT_EQ((Size{-128, 25}.MipCount()), 1u);
612 ASSERT_EQ((Size{1, 1}.MipCount()), 1u);
613 ASSERT_EQ((Size{0, 0}.MipCount()), 1u);
614 }

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

## ◆ TEST() [142/370]

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

Definition at line 639 of file geometry_unittests.cc.

639 {
640 {
641 IPoint p1(1, 2);
642 IPoint p2 = p1 + IPoint(1, 2);
643 ASSERT_EQ(p2.x, 2u);
644 ASSERT_EQ(p2.y, 4u);
645 }
646
647 {
648 IPoint p1(3, 6);
649 IPoint p2 = p1 - IPoint(1, 2);
650 ASSERT_EQ(p2.x, 2u);
651 ASSERT_EQ(p2.y, 4u);
652 }
653
654 {
655 IPoint p1(1, 2);
656 IPoint p2 = p1 * IPoint(2, 3);
657 ASSERT_EQ(p2.x, 2u);
658 ASSERT_EQ(p2.y, 6u);
659 }
660
661 {
662 IPoint p1(2, 6);
663 IPoint p2 = p1 / IPoint(2, 3);
664 ASSERT_EQ(p2.x, 1u);
665 ASSERT_EQ(p2.y, 2u);
666 }
667 }

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

## ◆ TEST() [143/370]

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

Definition at line 669 of file geometry_unittests.cc.

669 {
670 // LHS
671 {
672 IPoint p1(1, 2);
673 IPoint p2 = p1 * 2.0f;
674 ASSERT_EQ(p2.x, 2u);
675 ASSERT_EQ(p2.y, 4u);
676 }
677
678 {
679 IPoint p1(2, 6);
680 IPoint p2 = p1 / 2.0f;
681 ASSERT_EQ(p2.x, 1u);
682 ASSERT_EQ(p2.y, 3u);
683 }
684
685 // RHS
686 {
687 IPoint p1(1, 2);
688 IPoint p2 = 2.0f * p1;
689 ASSERT_EQ(p2.x, 2u);
690 ASSERT_EQ(p2.y, 4u);
691 }
692
693 {
694 IPoint p1(2, 6);
695 IPoint p2 = 12.0f / p1;
696 ASSERT_EQ(p2.x, 6u);
697 ASSERT_EQ(p2.y, 2u);
698 }
699 }

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

## ◆ TEST() [144/370]

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

Definition at line 1173 of file geometry_unittests.cc.

1173 {
1174 {
1175 Vector3 p1(1, 2, 3);
1176 Vector3 p2 = p1 + Vector3(1, 2, 3);
1177 ASSERT_EQ(p2.x, 2u);
1178 ASSERT_EQ(p2.y, 4u);
1179 ASSERT_EQ(p2.z, 6u);
1180 }
1181
1182 {
1183 Vector3 p1(3, 6, 9);
1184 Vector3 p2 = p1 - Vector3(1, 2, 3);
1185 ASSERT_EQ(p2.x, 2u);
1186 ASSERT_EQ(p2.y, 4u);
1187 ASSERT_EQ(p2.z, 6u);
1188 }
1189
1190 {
1191 Vector3 p1(1, 2, 3);
1192 Vector3 p2 = p1 * Vector3(2, 3, 4);
1193 ASSERT_EQ(p2.x, 2u);
1194 ASSERT_EQ(p2.y, 6u);
1195 ASSERT_EQ(p2.z, 12u);
1196 }
1197
1198 {
1199 Vector3 p1(2, 6, 12);
1200 Vector3 p2 = p1 / Vector3(2, 3, 4);
1201 ASSERT_EQ(p2.x, 1u);
1202 ASSERT_EQ(p2.y, 2u);
1203 ASSERT_EQ(p2.z, 3u);
1204 }
1205 }

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

## ◆ TEST() [145/370]

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

Definition at line 1207 of file geometry_unittests.cc.

1207 {
1208 // LHS
1209 {
1210 Vector3 p1(1, 2, 3);
1211 Vector3 p2 = p1 + 2.0f;
1212 ASSERT_EQ(p2.x, 3);
1213 ASSERT_EQ(p2.y, 4);
1214 ASSERT_EQ(p2.z, 5);
1215 }
1216
1217 {
1218 Vector3 p1(1, 2, 3);
1219 Vector3 p2 = p1 - 2.0f;
1220 ASSERT_EQ(p2.x, -1);
1221 ASSERT_EQ(p2.y, 0);
1222 ASSERT_EQ(p2.z, 1);
1223 }
1224
1225 {
1226 Vector3 p1(1, 2, 3);
1227 Vector3 p2 = p1 * 2.0f;
1228 ASSERT_EQ(p2.x, 2);
1229 ASSERT_EQ(p2.y, 4);
1230 ASSERT_EQ(p2.z, 6);
1231 }
1232
1233 {
1234 Vector3 p1(2, 6, 12);
1235 Vector3 p2 = p1 / 2.0f;
1236 ASSERT_EQ(p2.x, 1);
1237 ASSERT_EQ(p2.y, 3);
1238 ASSERT_EQ(p2.z, 6);
1239 }
1240
1241 // RHS
1242 {
1243 Vector3 p1(1, 2, 3);
1244 Vector3 p2 = 2.0f + p1;
1245 ASSERT_EQ(p2.x, 3);
1246 ASSERT_EQ(p2.y, 4);
1247 ASSERT_EQ(p2.z, 5);
1248 }
1249
1250 {
1251 Vector3 p1(1, 2, 3);
1252 Vector3 p2 = 2.0f - p1;
1253 ASSERT_EQ(p2.x, 1);
1254 ASSERT_EQ(p2.y, 0);
1255 ASSERT_EQ(p2.z, -1);
1256 }
1257
1258 {
1259 Vector3 p1(1, 2, 3);
1260 Vector3 p2 = 2.0f * p1;
1261 ASSERT_EQ(p2.x, 2);
1262 ASSERT_EQ(p2.y, 4);
1263 ASSERT_EQ(p2.z, 6);
1264 }
1265
1266 {
1267 Vector3 p1(2, 6, 12);
1268 Vector3 p2 = 12.0f / p1;
1269 ASSERT_EQ(p2.x, 6);
1270 ASSERT_EQ(p2.y, 2);
1271 ASSERT_EQ(p2.z, 1);
1272 }
1273 }

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

## ◆ TEST() [146/370]

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

Definition at line 821 of file geometry_unittests.cc.

821 {
822 // Point on RHS
823 {
824 IPoint p(1, 2);
825 p += IPoint(1, 2);
826 ASSERT_EQ(p.x, 2u);
827 ASSERT_EQ(p.y, 4u);
828 }
829
830 {
831 IPoint p(3, 6);
832 p -= IPoint(1, 2);
833 ASSERT_EQ(p.x, 2u);
834 ASSERT_EQ(p.y, 4u);
835 }
836
837 {
838 IPoint p(1, 2);
839 p *= IPoint(2, 3);
840 ASSERT_EQ(p.x, 2u);
841 ASSERT_EQ(p.y, 6u);
842 }
843
844 {
845 IPoint p(2, 6);
846 p /= IPoint(2, 3);
847 ASSERT_EQ(p.x, 1u);
848 ASSERT_EQ(p.y, 2u);
849 }
850
851 // Size on RHS
852 {
853 IPoint p(1, 2);
854 p += ISize(1, 2);
855 ASSERT_EQ(p.x, 2u);
856 ASSERT_EQ(p.y, 4u);
857 }
858
859 {
860 IPoint p(3, 6);
861 p -= ISize(1, 2);
862 ASSERT_EQ(p.x, 2u);
863 ASSERT_EQ(p.y, 4u);
864 }
865
866 {
867 IPoint p(1, 2);
868 p *= ISize(2, 3);
869 ASSERT_EQ(p.x, 2u);
870 ASSERT_EQ(p.y, 6u);
871 }
872
873 {
874 IPoint p(2, 6);
875 p /= ISize(2, 3);
876 ASSERT_EQ(p.x, 1u);
877 ASSERT_EQ(p.y, 2u);
878 }
879
880 // Arithmetic type on RHS
881 {
882 IPoint p(1, 2);
883 p *= 3;
884 ASSERT_EQ(p.x, 3u);
885 ASSERT_EQ(p.y, 6u);
886 }
887
888 {
889 IPoint p(3, 6);
890 p /= 3;
891 ASSERT_EQ(p.x, 1u);
892 ASSERT_EQ(p.y, 2u);
893 }
894 }

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

## ◆ TEST() [147/370]

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

Definition at line 1123 of file geometry_unittests.cc.

1123 {
1124 {
1125 Vector3 p(1, 2, 4);
1126 p += Vector3(1, 2, 4);
1127 ASSERT_EQ(p.x, 2u);
1128 ASSERT_EQ(p.y, 4u);
1129 ASSERT_EQ(p.z, 8u);
1130 }
1131
1132 {
1133 Vector3 p(3, 6, 8);
1134 p -= Vector3(1, 2, 3);
1135 ASSERT_EQ(p.x, 2u);
1136 ASSERT_EQ(p.y, 4u);
1137 ASSERT_EQ(p.z, 5u);
1138 }
1139
1140 {
1141 Vector3 p(1, 2, 3);
1142 p *= Vector3(2, 3, 4);
1143 ASSERT_EQ(p.x, 2u);
1144 ASSERT_EQ(p.y, 6u);
1145 ASSERT_EQ(p.z, 12u);
1146 }
1147
1148 {
1149 Vector3 p(1, 2, 3);
1150 p *= 2;
1151 ASSERT_EQ(p.x, 2u);
1152 ASSERT_EQ(p.y, 4u);
1153 ASSERT_EQ(p.z, 6u);
1154 }
1155
1156 {
1157 Vector3 p(2, 6, 12);
1158 p /= Vector3(2, 3, 4);
1159 ASSERT_EQ(p.x, 1u);
1160 ASSERT_EQ(p.y, 2u);
1161 ASSERT_EQ(p.z, 3u);
1162 }
1163
1164 {
1165 Vector3 p(2, 6, 12);
1166 p /= 2;
1167 ASSERT_EQ(p.x, 1u);
1168 ASSERT_EQ(p.y, 3u);
1169 ASSERT_EQ(p.z, 6u);
1170 }
1171 }

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

## ◆ TEST() [148/370]

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

Definition at line 1380 of file geometry_unittests.cc.

1380 {
1381 {
1382 ColorMatrix color_matrix = {
1383 1, 1, 1, 1, 1, //
1384 1, 1, 1, 1, 1, //
1385 1, 1, 1, 1, 1, //
1386 1, 1, 1, 1, 1, //
1387 };
1388 auto result = Color::White().ApplyColorMatrix(color_matrix);
1389 auto expected = Color(1, 1, 1, 1);
1390 ASSERT_COLOR_NEAR(result, expected);
1391 }
1392
1393 {
1394 ColorMatrix color_matrix = {
1395 0.1, 0, 0, 0, 0.01, //
1396 0, 0.2, 0, 0, 0.02, //
1397 0, 0, 0.3, 0, 0.03, //
1398 0, 0, 0, 0.4, 0.04, //
1399 };
1400 auto result = Color::White().ApplyColorMatrix(color_matrix);
1401 auto expected = Color(0.11, 0.22, 0.33, 0.44);
1402 ASSERT_COLOR_NEAR(result, expected);
1403 }
1404 }

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

## ◆ TEST() [149/370]

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

Definition at line 1584 of file geometry_unittests.cc.

1584 {
1585 using BlendT = std::underlying_type_t<BlendMode>;
1586 Color dst = ColorBlendTestData::kDestinationColor;
1587 for (size_t source_i = 0;
1588 source_i < sizeof(ColorBlendTestData::kSourceColors) / sizeof(Color);
1589 source_i++) {
1590 Color src = ColorBlendTestData::kSourceColors[source_i];
1591
1592 size_t blend_i;
1593 Color expected;
1594 IMPELLER_FOR_EACH_BLEND_MODE(_BLEND_MODE_RESULT_CHECK)
1595 }
1596 }

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

## ◆ TEST() [150/370]

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

Definition at line 1340 of file geometry_unittests.cc.

1340 {
1341 {
1342 Color result = Color(0.5, 0.5, 0.5, 0.5).Clamp01();
1343 Color expected = Color(0.5, 0.5, 0.5, 0.5);
1344 ASSERT_COLOR_NEAR(result, expected);
1345 }
1346
1347 {
1348 Color result = Color(-1, -1, -1, -1).Clamp01();
1349 Color expected = Color(0, 0, 0, 0);
1350 ASSERT_COLOR_NEAR(result, expected);
1351 }
1352
1353 {
1354 Color result = Color(2, 2, 2, 2).Clamp01();
1355 Color expected = Color(1, 1, 1, 1);
1356 ASSERT_COLOR_NEAR(result, expected);
1357 }
1358 }

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

## ◆ TEST() [151/370]

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

Definition at line 1318 of file geometry_unittests.cc.

1318 {
1319 {
1320 Color a(0.0, 0.0, 0.0, 0.0);
1321 Color b(1.0, 1.0, 1.0, 1.0);
1322
1323 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.5), Color(0.5, 0.5, 0.5, 0.5));
1324 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.0), a);
1325 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 1.0), b);
1326 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.2), Color(0.2, 0.2, 0.2, 0.2));
1327 }
1328
1329 {
1330 Color a(0.2, 0.4, 1.0, 0.5);
1331 Color b(0.4, 1.0, 0.2, 0.3);
1332
1333 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.5), Color(0.3, 0.7, 0.6, 0.4));
1334 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.0), a);
1335 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 1.0), b);
1336 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.2), Color(0.24, 0.52, 0.84, 0.46));
1337 }
1338 }

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

## ◆ TEST() [152/370]

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

Definition at line 1406 of file geometry_unittests.cc.

1406 {
1407 {
1408 auto result = Color::White().LinearToSRGB();
1409 auto expected = Color(1, 1, 1, 1);
1410 ASSERT_COLOR_NEAR(result, expected);
1411 }
1412
1413 {
1414 auto result = Color::BlackTransparent().LinearToSRGB();
1415 auto expected = Color(0, 0, 0, 0);
1416 ASSERT_COLOR_NEAR(result, expected);
1417 }
1418
1419 {
1420 auto result = Color(0.2, 0.4, 0.6, 0.8).LinearToSRGB();
1421 auto expected = Color(0.484529, 0.665185, 0.797738, 0.8);
1422 ASSERT_COLOR_NEAR(result, expected);
1423 }
1424 }

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

## ◆ TEST() [153/370]

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

Definition at line 1360 of file geometry_unittests.cc.

1360 {
1361 {
1362 Color a = Color::MakeRGBA8(0, 0, 0, 0);
1363 Color b = Color::BlackTransparent();
1364 ASSERT_COLOR_NEAR(a, b);
1365 }
1366
1367 {
1368 Color a = Color::MakeRGBA8(255, 255, 255, 255);
1369 Color b = Color::White();
1370 ASSERT_COLOR_NEAR(a, b);
1371 }
1372
1373 {
1374 Color a = Color::MakeRGBA8(63, 127, 191, 127);
1375 Color b(0.247059, 0.498039, 0.74902, 0.498039);
1376 ASSERT_COLOR_NEAR(a, b);
1377 }
1378 }

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

## ◆ TEST() [154/370]

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

Definition at line 1275 of file geometry_unittests.cc.

1275 {
1276 {
1277 Color a(1.0, 0.5, 0.2, 0.5);
1278 Color premultiplied = a.Premultiply();
1279 Color expected = Color(0.5, 0.25, 0.1, 0.5);
1280 ASSERT_COLOR_NEAR(premultiplied, expected);
1281 }
1282
1283 {
1284 Color a(0.5, 0.25, 0.1, 0.5);
1285 Color unpremultiplied = a.Unpremultiply();
1286 Color expected = Color(1.0, 0.5, 0.2, 0.5);
1287 ASSERT_COLOR_NEAR(unpremultiplied, expected);
1288 }
1289
1290 {
1291 Color a(0.5, 0.25, 0.1, 0.0);
1292 Color unpremultiplied = a.Unpremultiply();
1293 Color expected = Color(0.0, 0.0, 0.0, 0.0);
1294 ASSERT_COLOR_NEAR(unpremultiplied, expected);
1295 }
1296 }

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

## ◆ TEST() [155/370]

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

Definition at line 1695 of file geometry_unittests.cc.

1695 {
1696 {
1697 std::stringstream stream;
1698 Color m;
1699 stream << m;
1700 ASSERT_EQ(stream.str(), "(0, 0, 0, 0)");
1701 }
1702
1703 {
1704 std::stringstream stream;
1705 Color m(1, 2, 3, 4);
1706 stream << m;
1707 ASSERT_EQ(stream.str(), "(1, 2, 3, 4)");
1708 }
1709 }

## ◆ TEST() [156/370]

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

Definition at line 1298 of file geometry_unittests.cc.

1298 {
1299 {
1300 Color a(1.0, 0.5, 0.2, 0.5);
1301 std::array<uint8_t, 4> expected = {255, 128, 51, 128};
1302 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1303 }
1304
1305 {
1306 Color a(0.0, 0.0, 0.0, 0.0);
1307 std::array<uint8_t, 4> expected = {0, 0, 0, 0};
1308 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1309 }
1310
1311 {
1312 Color a(1.0, 1.0, 1.0, 1.0);
1313 std::array<uint8_t, 4> expected = {255, 255, 255, 255};
1314 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1315 }
1316 }

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

## ◆ TEST() [157/370]

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

Definition at line 1426 of file geometry_unittests.cc.

1426 {
1427 {
1428 auto result = Color::White().SRGBToLinear();
1429 auto expected = Color(1, 1, 1, 1);
1430 ASSERT_COLOR_NEAR(result, expected);
1431 }
1432
1433 {
1434 auto result = Color::BlackTransparent().SRGBToLinear();
1435 auto expected = Color(0, 0, 0, 0);
1436 ASSERT_COLOR_NEAR(result, expected);
1437 }
1438
1439 {
1440 auto result = Color(0.2, 0.4, 0.6, 0.8).SRGBToLinear();
1441 auto expected = Color(0.0331048, 0.132868, 0.318547, 0.8);
1442 ASSERT_COLOR_NEAR(result, expected);
1443 }
1444 }

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

## ◆ TEST() [158/370]

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

Definition at line 115 of file geometry_unittests.cc.

115 {
116 auto matrix = Matrix{3, 4, 14, 155, 2, 1, 3, 4, 2, 3, 2, 1, 1, 2, 4, 2};
117 ASSERT_EQ(matrix.GetDeterminant(), -1889);
118 }

## ◆ TEST() [159/370]

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

Definition at line 1717 of file geometry_unittests.cc.

1717 {
1718 {
1719 // Simple 2 color gradient produces color buffer containing exactly those
1720 // values.
1721 std::vector<Color> colors = {Color::Red(), Color::Blue()};
1722 std::vector<Scalar> stops = {0.0, 1.0};
1723
1724 auto gradient = CreateGradientBuffer(colors, stops);
1725
1726 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, colors);
1727 ASSERT_EQ(gradient.texture_size, 2u);
1728 }
1729
1730 {
1731 // Gradient with duplicate stops does not create an empty texture.
1732 std::vector<Color> colors = {Color::Red(), Color::Yellow(), Color::Black(),
1733 Color::Blue()};
1734 std::vector<Scalar> stops = {0.0, 0.25, 0.25, 1.0};
1735
1736 auto gradient = CreateGradientBuffer(colors, stops);
1737 ASSERT_EQ(gradient.texture_size, 5u);
1738 }
1739
1740 {
1741 // Simple N color gradient produces color buffer containing exactly those
1742 // values.
1743 std::vector<Color> colors = {Color::Red(), Color::Blue(), Color::Green(),
1744 Color::White()};
1745 std::vector<Scalar> stops = {0.0, 0.33, 0.66, 1.0};
1746
1747 auto gradient = CreateGradientBuffer(colors, stops);
1748
1749 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, colors);
1750 ASSERT_EQ(gradient.texture_size, 4u);
1751 }
1752
1753 {
1754 // Gradient with color stops will lerp and scale buffer.
1755 std::vector<Color> colors = {Color::Red(), Color::Blue(), Color::Green()};
1756 std::vector<Scalar> stops = {0.0, 0.25, 1.0};
1757
1758 auto gradient = CreateGradientBuffer(colors, stops);
1759
1760 std::vector<Color> lerped_colors = {
1761 Color::Red(),
1762 Color::Blue(),
1763 Color::Lerp(Color::Blue(), Color::Green(), 0.3333),
1764 Color::Lerp(Color::Blue(), Color::Green(), 0.6666),
1765 Color::Green(),
1766 };
1767 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, lerped_colors);
1768 ASSERT_EQ(gradient.texture_size, 5u);
1769 }
1770
1771 {
1772 // Gradient size is capped at 1024.
1773 std::vector<Color> colors = {};
1774 std::vector<Scalar> stops = {};
1775 for (auto i = 0u; i < 1025; i++) {
1776 colors.push_back(Color::Blue());
1777 stops.push_back(i / 1025.0);
1778 }
1779
1780 auto gradient = CreateGradientBuffer(colors, stops);
1781
1782 ASSERT_EQ(gradient.texture_size, 1024u);
1783 ASSERT_EQ(gradient.color_bytes.size(), 1024u * 4);
1784 }
1785 }

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

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

Definition at line 1787 of file geometry_unittests.cc.

1787 {
1788 #if defined(FML_OS_MACOSX) || defined(FML_OS_IOS) || \
1789 defined(FML_OS_IOS_SIMULATOR)
1790 ASSERT_EQ(ScalarToHalf(0.0), 0.0f16);
1791 ASSERT_EQ(ScalarToHalf(0.05), 0.05f16);
1792 ASSERT_EQ(ScalarToHalf(2.43), 2.43f16);
1793 ASSERT_EQ(ScalarToHalf(-1.45), -1.45f16);
1794
1795 // 65504 is the largest possible half.
1796 ASSERT_EQ(ScalarToHalf(65504.0f), 65504.0f16);
1797 ASSERT_EQ(ScalarToHalf(65504.0f + 1), 65504.0f16);
1798
1799 // Colors
1800 ASSERT_EQ(HalfVector4(Color::Red()),
1801 HalfVector4(1.0f16, 0.0f16, 0.0f16, 1.0f16));
1802 ASSERT_EQ(HalfVector4(Color::Green()),
1803 HalfVector4(0.0f16, 1.0f16, 0.0f16, 1.0f16));
1804 ASSERT_EQ(HalfVector4(Color::Blue()),
1805 HalfVector4(0.0f16, 0.0f16, 1.0f16, 1.0f16));
1806 ASSERT_EQ(HalfVector4(Color::Black().WithAlpha(0)),
1807 HalfVector4(0.0f16, 0.0f16, 0.0f16, 0.0f16));
1808
1809 ASSERT_EQ(HalfVector3(Vector3(4.0, 6.0, -1.0)),
1810 HalfVector3(4.0f16, 6.0f16, -1.0f16));
1811 ASSERT_EQ(HalfVector2(Vector2(4.0, 6.0)), HalfVector2(4.0f16, 6.0f16));
1812
1813 ASSERT_EQ(Half(0.5f), Half(0.5f16));
1814 ASSERT_EQ(Half(0.5), Half(0.5f16));
1815 ASSERT_EQ(Half(5), Half(5.0f16));
1816 #else
1817 GTEST_SKIP() << "Half-precision floats (IEEE 754) are not portable and "
1818 "only used on Apple platforms.";
1819 #endif // FML_OS_MACOSX || FML_OS_IOS || FML_OS_IOS_SIMULATOR
1820 }

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

## ◆ TEST() [161/370]

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

Definition at line 120 of file geometry_unittests.cc.

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

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

## ◆ TEST() [162/370]

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

Definition at line 75 of file geometry_unittests.cc.

75 {
76 {
77 auto rotation = Matrix::MakeRotationZ(Radians{kPiOver4});
78 auto invert = rotation.Invert();
79 auto expect = Matrix{0.707, -0.707, 0, 0, //
80 0.707, 0.707, 0, 0, //
81 0, 0, 1, 0, //
82 0, 0, 0, 1};
83 ASSERT_MATRIX_NEAR(invert, expect);
84 }
85 {
86 auto scale = Matrix::MakeScale(Vector2{2, 4});
87 auto invert = scale.Invert();
88 auto expect = Matrix{0.5, 0, 0, 0, //
89 0, 0.25, 0, 0, //
90 0, 0, 1, 0, //
91 0, 0, 0, 1};
92 ASSERT_MATRIX_NEAR(invert, expect);
93 }
94 }

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

## ◆ TEST() [163/370]

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

Definition at line 38 of file geometry_unittests.cc.

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

References impeller::Matrix::MakeColumn().

## ◆ TEST() [164/370]

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

Definition at line 52 of file geometry_unittests.cc.

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

References impeller::Matrix::MakeRow().

## ◆ TEST() [165/370]

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

Definition at line 96 of file geometry_unittests.cc.

96 {
97 auto matrix = Matrix{1, 2, 3, 4, //
98 5, 6, 7, 8, //
99 9, 10, 11, 12, //
100 13, 14, 15, 16};
101 auto basis = matrix.Basis();
102 auto expect = Matrix{1, 2, 3, 0, //
103 5, 6, 7, 0, //
104 9, 10, 11, 0, //
105 0, 0, 0, 1};
106 ASSERT_MATRIX_NEAR(basis, expect);
107 }

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

## ◆ TEST() [166/370]

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

Definition at line 417 of file geometry_unittests.cc.

417 {
418 {
419 auto m = Matrix();
420 Vector3 x = m.GetBasisX();
421 Vector3 y = m.GetBasisY();
422 Vector3 z = m.GetBasisZ();
423 ASSERT_VECTOR3_NEAR(x, Vector3(1, 0, 0));
424 ASSERT_VECTOR3_NEAR(y, Vector3(0, 1, 0));
425 ASSERT_VECTOR3_NEAR(z, Vector3(0, 0, 1));
426 }
427
428 {
429 auto m = Matrix::MakeRotationZ(Radians{kPiOver2}) *
430 Matrix::MakeRotationX(Radians{kPiOver2}) *
431 Matrix::MakeScale(Vector3(2, 3, 4));
432 Vector3 x = m.GetBasisX();
433 Vector3 y = m.GetBasisY();
434 Vector3 z = m.GetBasisZ();
435 ASSERT_VECTOR3_NEAR(x, Vector3(0, 2, 0));
436 ASSERT_VECTOR3_NEAR(y, Vector3(0, 0, 3));
437 ASSERT_VECTOR3_NEAR(z, Vector3(4, 0, 0));
438 }
439 }

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

## ◆ TEST() [167/370]

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

Definition at line 441 of file geometry_unittests.cc.

441 {
442 {
443 auto m = Matrix();
444 Scalar result = m.GetDirectionScale(Vector3{1, 0, 0});
445 ASSERT_FLOAT_EQ(result, 1);
446 }
447
448 {
449 auto m = Matrix::MakeRotationX(Degrees{10}) *
450 Matrix::MakeRotationY(Degrees{83}) *
451 Matrix::MakeRotationZ(Degrees{172});
452 Scalar result = m.GetDirectionScale(Vector3{0, 1, 0});
453 ASSERT_FLOAT_EQ(result, 1);
454 }
455
456 {
457 auto m = Matrix::MakeRotationZ(Radians{kPiOver2}) *
458 Matrix::MakeScale(Vector3(3, 4, 5));
459 Scalar result = m.GetDirectionScale(Vector3{2, 0, 0});
460 ASSERT_FLOAT_EQ(result, 8);
461 }
462 }

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

## ◆ TEST() [168/370]

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

Definition at line 327 of file geometry_unittests.cc.

327 {
328 {
329 auto m = Matrix::MakeScale({3, 1, 1});
330 ASSERT_EQ(m.GetMaxBasisLength(), 3);
331
332 m = m * Matrix::MakeSkew(0, 4);
333 ASSERT_EQ(m.GetMaxBasisLength(), 5);
334 }
335
336 {
337 auto m = Matrix::MakeScale({-3, 4, 2});
338 ASSERT_EQ(m.GetMaxBasisLength(), 4);
339 }
340 }

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

## ◆ TEST() [169/370]

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

Definition at line 342 of file geometry_unittests.cc.

342 {
343 {
344 auto m = Matrix::MakeScale({3, 1, 1});
345 ASSERT_EQ(m.GetMaxBasisLengthXY(), 3);
346
347 m = m * Matrix::MakeSkew(0, 4);
348 ASSERT_EQ(m.GetMaxBasisLengthXY(), 5);
349 }
350
351 {
352 auto m = Matrix::MakeScale({-3, 4, 7});
353 ASSERT_EQ(m.GetMaxBasisLengthXY(), 4);
354 }
355
356 {
357 // clang-format off
358 auto m = Matrix::MakeColumn(
359 1.0f, 0.0f, 0.0f, 0.0f,
360 0.0f, 1.0f, 0.0f, 0.0f,
361 4.0f, 0.0f, 1.0f, 0.0f,
362 0.0f, 0.0f, 0.0f, 1.0f
363 );
364 // clang-format on
365 ASSERT_EQ(m.GetMaxBasisLengthXY(), 1.0f);
366 }
367 }

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

## ◆ TEST() [170/370]

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

Definition at line 464 of file geometry_unittests.cc.

464 {
465 {
466 auto m = Matrix::MakeTranslation({1, 2, 3});
467 bool result = m.IsAligned();
468 ASSERT_TRUE(result);
469 }
470
471 {
472 auto m = Matrix::MakeRotationZ(Degrees{123});
473 bool result = m.IsAligned();
474 ASSERT_FALSE(result);
475 }
476 }

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

## ◆ TEST() [171/370]

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

Definition at line 504 of file geometry_unittests.cc.

504 {
505 {
506 auto m = Matrix::MakeLookAt(Vector3(0, 0, -1), Vector3(0, 0, 1),
507 Vector3(0, 1, 0));
508 auto expected = Matrix{
509 1, 0, 0, 0, //
510 0, 1, 0, 0, //
511 0, 0, 1, 0, //
512 0, 0, 1, 1, //
513 };
514 ASSERT_MATRIX_NEAR(m, expected);
515 }
516
517 // Sideways tilt.
518 {
519 auto m = Matrix::MakeLookAt(Vector3(0, 0, -1), Vector3(0, 0, 1),
520 Vector3(1, 1, 0).Normalize());
521
522 // clang-format off
523 auto expected = Matrix{
524 k1OverSqrt2, k1OverSqrt2, 0, 0,
525 -k1OverSqrt2, k1OverSqrt2, 0, 0,
526 0, 0, 1, 0,
527 0, 0, 1, 1,
528 };
529 // clang-format on
530 ASSERT_MATRIX_NEAR(m, expected);
531 }
532
533 // Half way between +x and -y, yaw 90
534 {
535 auto m =
536 Matrix::MakeLookAt(Vector3(), Vector3(10, -10, 0), Vector3(0, 0, -1));
537
538 // clang-format off
539 auto expected = Matrix{
540 -k1OverSqrt2, 0, k1OverSqrt2, 0,
541 -k1OverSqrt2, 0, -k1OverSqrt2, 0,
542 0, -1, 0, 0,
543 0, 0, 0, 1,
544 };
545 // clang-format on
546 ASSERT_MATRIX_NEAR(m, expected);
547 }
548 }

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

## ◆ TEST() [172/370]

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

Definition at line 369 of file geometry_unittests.cc.

369 {
370 {
371 auto m = Matrix::MakeOrthographic(Size(100, 200));
372 auto expect = Matrix{
373 0.02, 0, 0, 0, //
374 0, -0.01, 0, 0, //
375 0, 0, 0, 0, //
376 -1, 1, 0.5, 1, //
377 };
378 ASSERT_MATRIX_NEAR(m, expect);
379 }
380
381 {
382 auto m = Matrix::MakeOrthographic(Size(400, 100));
383 auto expect = Matrix{
384 0.005, 0, 0, 0, //
385 0, -0.02, 0, 0, //
386 0, 0, 0, 0, //
387 -1, 1, 0.5, 1, //
388 };
389 ASSERT_MATRIX_NEAR(m, expect);
390 }
391 }

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

## ◆ TEST() [173/370]

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

Definition at line 393 of file geometry_unittests.cc.

393 {
394 {
395 auto m = Matrix::MakePerspective(Degrees(60), Size(100, 200), 1, 10);
396 auto expect = Matrix{
397 3.4641, 0, 0, 0, //
398 0, 1.73205, 0, 0, //
399 0, 0, 1.11111, 1, //
400 0, 0, -1.11111, 0, //
401 };
402 ASSERT_MATRIX_NEAR(m, expect);
403 }
404
405 {
406 auto m = Matrix::MakePerspective(Radians(1), 2, 10, 20);
407 auto expect = Matrix{
408 0.915244, 0, 0, 0, //
409 0, 1.83049, 0, 0, //
410 0, 0, 2, 1, //
411 0, 0, -20, 0, //
412 };
413 ASSERT_MATRIX_NEAR(m, expect);
414 }
415 }

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

## ◆ TEST() [174/370]

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

Definition at line 272 of file geometry_unittests.cc.

272 {
273 {
274 auto matrix = Matrix::MakeRotation(Quaternion({1, 0, 0}, kPiOver2));
275 auto expected = Matrix::MakeRotationX(Radians(kPiOver2));
276 ASSERT_MATRIX_NEAR(matrix, expected);
277 }
278
279 {
280 auto matrix = Matrix::MakeRotation(Quaternion({0, 1, 0}, kPiOver2));
281 auto expected = Matrix::MakeRotationY(Radians(kPiOver2));
282 ASSERT_MATRIX_NEAR(matrix, expected);
283 }
284
285 {
286 auto matrix = Matrix::MakeRotation(Quaternion({0, 0, 1}, kPiOver2));
287 auto expected = Matrix::MakeRotationZ(Radians(kPiOver2));
288 ASSERT_MATRIX_NEAR(matrix, expected);
289 }
290 }

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

## ◆ TEST() [175/370]

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

Definition at line 1620 of file geometry_unittests.cc.

1620 {
1621 {
1622 std::stringstream stream;
1623 Matrix m;
1624 stream << m;
1625 ASSERT_EQ(stream.str(), R"((
1626 1.000000, 0.000000, 0.000000, 0.000000,
1627 0.000000, 1.000000, 0.000000, 0.000000,
1628 0.000000, 0.000000, 1.000000, 0.000000,
1629 0.000000, 0.000000, 0.000000, 1.000000,
1630 ))");
1631 }
1632
1633 {
1634 std::stringstream stream;
1635 Matrix m = Matrix::MakeTranslation(Vector3(10, 20, 30));
1636 stream << m;
1637
1638 ASSERT_EQ(stream.str(), R"((
1639 1.000000, 0.000000, 0.000000, 10.000000,
1640 0.000000, 1.000000, 0.000000, 20.000000,
1641 0.000000, 0.000000, 1.000000, 30.000000,
1642 0.000000, 0.000000, 0.000000, 1.000000,
1643 ))");
1644 }
1645 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST() [176/370]

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

Definition at line 292 of file geometry_unittests.cc.

292 {
293 {
294 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
295 Matrix::MakeRotationZ(Radians{kPiOver2}) *
296 Matrix::MakeScale({2.0, 2.0, 2.0});
297 auto vector = Vector4(10, 20, 30, 2);
298
299 Vector4 result = matrix.TransformDirection(vector);
300 auto expected = Vector4(-40, 20, 60, 2);
301 ASSERT_VECTOR4_NEAR(result, expected);
302 }
303
304 {
305 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
306 Matrix::MakeRotationZ(Radians{kPiOver2}) *
307 Matrix::MakeScale({2.0, 2.0, 2.0});
308 auto vector = Vector3(10, 20, 30);
309
310 Vector3 result = matrix.TransformDirection(vector);
311 auto expected = Vector3(-40, 20, 60);
312 ASSERT_VECTOR3_NEAR(result, expected);
313 }
314
315 {
316 auto matrix = Matrix::MakeTranslation({0, -0.4, 100}) *
317 Matrix::MakeRotationZ(Radians{kPiOver2}) *
318 Matrix::MakeScale({2.0, 2.0, 2.0});
319 auto vector = Point(10, 20);
320
321 Point result = matrix.TransformDirection(vector);
322 auto expected = Point(-40, 20);
323 ASSERT_POINT_NEAR(result, expected);
324 }
325 }

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

## ◆ TEST() [177/370]

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

Definition at line 478 of file geometry_unittests.cc.

478 {
479 {
480 auto m = Matrix();
481 bool result = m.IsTranslationScaleOnly();
482 ASSERT_TRUE(result);
483 }
484
485 {
486 auto m = Matrix::MakeScale(Vector3(2, 3, 4));
487 bool result = m.IsTranslationScaleOnly();
488 ASSERT_TRUE(result);
489 }
490
491 {
492 auto m = Matrix::MakeTranslation(Vector3(2, 3, 4));
493 bool result = m.IsTranslationScaleOnly();
494 ASSERT_TRUE(result);
495 }
496
497 {
498 auto m = Matrix::MakeRotationZ(Degrees(10));
499 bool result = m.IsTranslationScaleOnly();
500 ASSERT_FALSE(result);
501 }
502 }

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

## ◆ TEST() [178/370]

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

Definition at line 207 of file geometry_unittests.cc.

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

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

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

Definition at line 109 of file geometry_unittests.cc.

109 {
110 auto rotation = Matrix::MakeRotationZ(Radians{kPiOver4});
111 auto invert = rotation.Invert();
112 ASSERT_MATRIX_NEAR(rotation * invert, Matrix{});
113 }

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

## ◆ TEST() [180/370]

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

Definition at line 961 of file geometry_unittests.cc.

961 {
962 Point a(-1, -2);
963 auto a_abs = a.Abs();
964 auto expected = Point(1, 2);
965 ASSERT_POINT_NEAR(a_abs, expected);
966 }

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

## ◆ TEST() [181/370]

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

Definition at line 968 of file geometry_unittests.cc.

968 {
969 // Negative result in the CCW (with up = -Y) direction.
970 {
971 Point a(1, 1);
972 Point b(1, -1);
973 Radians actual = a.AngleTo(b);
974 Radians expected = Radians{-kPi / 2};
975 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
976 }
977
978 // Check the other direction to ensure the result is signed correctly.
979 {
980 Point a(1, -1);
981 Point b(1, 1);
982 Radians actual = a.AngleTo(b);
983 Radians expected = Radians{kPi / 2};
984 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
985 }
986
987 // Differences in magnitude should have no impact on the result.
988 {
989 Point a(100, -100);
990 Point b(0.01, 0.01);
991 Radians actual = a.AngleTo(b);
992 Radians expected = Radians{kPi / 2};
993 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
994 }
995 }

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

## ◆ TEST() [182/370]

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

Definition at line 1060 of file geometry_unittests.cc.

1060 {
1061 Point p(1.5, 2.3);
1062 Point result = p.Ceil();
1063 Point expected(2, 3);
1064 ASSERT_POINT_NEAR(result, expected);
1065 }

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

## ◆ TEST() [183/370]

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

Definition at line 916 of file geometry_unittests.cc.

916 {
917 {
918 Point p(1, 0);
919 Scalar s = p.Cross(Point(-1, 0));
920 ASSERT_FLOAT_EQ(s, 0);
921 }
922
923 {
924 Point p(0, -1);
925 Scalar s = p.Cross(Point(-1, 0));
926 ASSERT_FLOAT_EQ(s, -1);
927 }
928
929 {
930 Point p(1, 2);
931 Scalar s = p.Cross(Point(3, -4));
932 ASSERT_FLOAT_EQ(s, -10);
933 }
934 }

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

## ◆ TEST() [184/370]

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

Definition at line 896 of file geometry_unittests.cc.

896 {
897 {
898 Point p(1, 0);
899 Scalar s = p.Dot(Point(-1, 0));
900 ASSERT_FLOAT_EQ(s, -1);
901 }
902
903 {
904 Point p(0, -1);
905 Scalar s = p.Dot(Point(-1, 0));
906 ASSERT_FLOAT_EQ(s, 0);
907 }
908
909 {
910 Point p(1, 2);
911 Scalar s = p.Dot(Point(3, -4));
912 ASSERT_FLOAT_EQ(s, -5);
913 }
914 }

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

## ◆ TEST() [185/370]

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

Definition at line 1039 of file geometry_unittests.cc.

1039 {
1040 Point p(1.5, 2.3);
1041 Point result = p.Floor();
1042 Point expected(1, 2);
1043 ASSERT_POINT_NEAR(result, expected);
1044 }

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

## ◆ TEST() [186/370]

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

Definition at line 701 of file geometry_unittests.cc.

701 {
702 // Integer on LHS, float on RHS
703 {
704 IPoint p1(1, 2);
705 Point p2 = p1 + Point(1, 2);
706 ASSERT_FLOAT_EQ(p2.x, 2u);
707 ASSERT_FLOAT_EQ(p2.y, 4u);
708 }
709
710 {
711 IPoint p1(3, 6);
712 Point p2 = p1 - Point(1, 2);
713 ASSERT_FLOAT_EQ(p2.x, 2u);
714 ASSERT_FLOAT_EQ(p2.y, 4u);
715 }
716
717 {
718 IPoint p1(1, 2);
719 Point p2 = p1 * Point(2, 3);
720 ASSERT_FLOAT_EQ(p2.x, 2u);
721 ASSERT_FLOAT_EQ(p2.y, 6u);
722 }
723
724 {
725 IPoint p1(2, 6);
726 Point p2 = p1 / Point(2, 3);
727 ASSERT_FLOAT_EQ(p2.x, 1u);
728 ASSERT_FLOAT_EQ(p2.y, 2u);
729 }
730
731 // Float on LHS, integer on RHS
732 {
733 Point p1(1, 2);
734 Point p2 = p1 + IPoint(1, 2);
735 ASSERT_FLOAT_EQ(p2.x, 2u);
736 ASSERT_FLOAT_EQ(p2.y, 4u);
737 }
738
739 {
740 Point p1(3, 6);
741 Point p2 = p1 - IPoint(1, 2);
742 ASSERT_FLOAT_EQ(p2.x, 2u);
743 ASSERT_FLOAT_EQ(p2.y, 4u);
744 }
745
746 {
747 Point p1(1, 2);
748 Point p2 = p1 * IPoint(2, 3);
749 ASSERT_FLOAT_EQ(p2.x, 2u);
750 ASSERT_FLOAT_EQ(p2.y, 6u);
751 }
752
753 {
754 Point p1(2, 6);
755 Point p2 = p1 / IPoint(2, 3);
756 ASSERT_FLOAT_EQ(p2.x, 1u);
757 ASSERT_FLOAT_EQ(p2.y, 2u);
758 }
759 }

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

## ◆ TEST() [187/370]

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

Definition at line 1102 of file geometry_unittests.cc.

1102 {
1103 Point p(1, 2);
1104 Point result = p.Lerp({5, 10}, 0.75);
1105 Point expected(4, 8);
1106 ASSERT_POINT_NEAR(result, expected);
1107 }

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

## ◆ TEST() [188/370]

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

Definition at line 1018 of file geometry_unittests.cc.

1018 {
1019 Point p(1, 2);
1020 Point result = p.Max({0, 10});
1021 Point expected(1, 10);
1022 ASSERT_POINT_NEAR(result, expected);
1023 }

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

## ◆ TEST() [189/370]

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

Definition at line 997 of file geometry_unittests.cc.

997 {
998 Point p(1, 2);
999 Point result = p.Min({0, 10});
1000 Point expected(0, 2);
1001 ASSERT_POINT_NEAR(result, expected);
1002 }

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

## ◆ TEST() [190/370]

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

Definition at line 1647 of file geometry_unittests.cc.

1647 {
1648 {
1649 std::stringstream stream;
1650 Point m;
1651 stream << m;
1652 ASSERT_EQ(stream.str(), "(0, 0)");
1653 }
1654
1655 {
1656 std::stringstream stream;
1657 Point m(13, 37);
1658 stream << m;
1659 ASSERT_EQ(stream.str(), "(13, 37)");
1660 }
1661 }

## ◆ TEST() [191/370]

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

Definition at line 936 of file geometry_unittests.cc.

936 {
937 {
938 Point axis = Point(0, 1);
939 Point a(2, 3);
940 auto reflected = a.Reflect(axis);
941 auto expected = Point(2, -3);
942 ASSERT_POINT_NEAR(reflected, expected);
943 }
944
945 {
946 Point axis = Point(1, 1).Normalize();
947 Point a(1, 0);
948 auto reflected = a.Reflect(axis);
949 auto expected = Point(0, -1);
950 ASSERT_POINT_NEAR(reflected, expected);
951 }
952
953 {
954 Point axis = Point(1, 1).Normalize();
955 Point a(-1, -1);
956 auto reflected = a.Reflect(axis);
957 ASSERT_POINT_NEAR(reflected, -a);
958 }
959 }

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

## ◆ TEST() [192/370]

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

Definition at line 1081 of file geometry_unittests.cc.

1081 {
1082 Point p(1.5, 2.3);
1083 Point result = p.Round();
1084 Point expected(2, 2);
1085 ASSERT_POINT_NEAR(result, expected);
1086 }

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

## ◆ TEST() [193/370]

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

Definition at line 550 of file geometry_unittests.cc.

550 {
551 auto q1 = Quaternion{{0.0, 0.0, 1.0}, 0.0};
552 auto q2 = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
553
554 auto q3 = q1.Slerp(q2, 0.5);
555
556 auto expected = Quaternion{{0.0, 0.0, 1.0}, kPiOver4 / 2.0};
557
558 ASSERT_QUATERNION_NEAR(q3, expected);
559 }

References ASSERT_QUATERNION_NEAR, and impeller::kPiOver4.

## ◆ TEST() [194/370]

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

Definition at line 561 of file geometry_unittests.cc.

561 {
562 {
563 Quaternion q({0, 0, 1}, 0);
564 Vector3 v(0, 1, 0);
565
566 Vector3 result = q * v;
567 Vector3 expected(0, 1, 0);
568
569 ASSERT_VECTOR3_NEAR(result, expected);
570 }
571
572 {
573 Quaternion q({0, 0, 1}, k2Pi);
574 Vector3 v(1, 0, 0);
575
576 Vector3 result = q * v;
577 Vector3 expected(1, 0, 0);
578
579 ASSERT_VECTOR3_NEAR(result, expected);
580 }
581
582 {
583 Quaternion q({0, 0, 1}, kPiOver4);
584 Vector3 v(0, 1, 0);
585
586 Vector3 result = q * v;
587 Vector3 expected(-k1OverSqrt2, k1OverSqrt2, 0);
588
589 ASSERT_VECTOR3_NEAR(result, expected);
590 }
591
592 {
593 Quaternion q(Vector3(1, 0, 1).Normalize(), kPi);
594 Vector3 v(0, 0, -1);
595
596 Vector3 result = q * v;
597 Vector3 expected(-1, 0, 0);
598
599 ASSERT_VECTOR3_NEAR(result, expected);
600 }
601 }

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

## ◆ TEST() [195/370]

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

Definition at line 66 of file geometry_unittests.cc.

66 {
67 auto rotation = Matrix::MakeRotationZ(Radians{kPiOver4});
68 auto expect = Matrix{0.707, 0.707, 0, 0, //
69 -0.707, 0.707, 0, 0, //
70 0, 0, 1, 0, //
71 0, 0, 0, 1};
72 ASSERT_MATRIX_NEAR(rotation, expect);
73 }

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

## ◆ TEST() [196/370]

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

Definition at line 29 of file geometry_unittests.cc.

29 {
30 ASSERT_FALSE(ScalarNearlyEqual(0.0021f, 0.001f));
31 ASSERT_TRUE(ScalarNearlyEqual(0.0019f, 0.001f));
32 ASSERT_TRUE(ScalarNearlyEqual(0.002f, 0.001f, 0.0011f));
33 ASSERT_FALSE(ScalarNearlyEqual(0.002f, 0.001f, 0.0009f));
34 ASSERT_TRUE(ScalarNearlyEqual(
35 1.0f, 1.0f + std::numeric_limits<float>::epsilon() * 4));
36 }

References impeller::ScalarNearlyEqual().

## ◆ TEST() [197/370]

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

Definition at line 761 of file geometry_unittests.cc.

761 {
762 // Point on LHS, Size on RHS
763 {
764 IPoint p1(1, 2);
765 IPoint p2 = p1 + ISize(1, 2);
766 ASSERT_EQ(p2.x, 2u);
767 ASSERT_EQ(p2.y, 4u);
768 }
769
770 {
771 IPoint p1(3, 6);
772 IPoint p2 = p1 - ISize(1, 2);
773 ASSERT_EQ(p2.x, 2u);
774 ASSERT_EQ(p2.y, 4u);
775 }
776
777 {
778 IPoint p1(1, 2);
779 IPoint p2 = p1 * ISize(2, 3);
780 ASSERT_EQ(p2.x, 2u);
781 ASSERT_EQ(p2.y, 6u);
782 }
783
784 {
785 IPoint p1(2, 6);
786 IPoint p2 = p1 / ISize(2, 3);
787 ASSERT_EQ(p2.x, 1u);
788 ASSERT_EQ(p2.y, 2u);
789 }
790
791 // Size on LHS, Point on RHS
792 {
793 ISize p1(1, 2);
794 IPoint p2 = p1 + IPoint(1, 2);
795 ASSERT_EQ(p2.x, 2u);
796 ASSERT_EQ(p2.y, 4u);
797 }
798
799 {
800 ISize p1(3, 6);
801 IPoint p2 = p1 - IPoint(1, 2);
802 ASSERT_EQ(p2.x, 2u);
803 ASSERT_EQ(p2.y, 4u);
804 }
805
806 {
807 ISize p1(1, 2);
808 IPoint p2 = p1 * IPoint(2, 3);
809 ASSERT_EQ(p2.x, 2u);
810 ASSERT_EQ(p2.y, 6u);
811 }
812
813 {
814 ISize p1(2, 6);
815 IPoint p2 = p1 / IPoint(2, 3);
816 ASSERT_EQ(p2.x, 1u);
817 ASSERT_EQ(p2.y, 2u);
818 }
819 }

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

## ◆ TEST() [198/370]

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

Definition at line 136 of file geometry_unittests.cc.

136 {
137 auto rotated = Matrix::MakeRotationZ(Radians{kPiOver4});
138
139 auto result = rotated.Decompose();
140
141 ASSERT_TRUE(result.has_value());
142
143 MatrixDecomposition res = result.value();
144
145 auto quaternion = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
146 ASSERT_QUATERNION_NEAR(res.rotation, quaternion);
147 }

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

## ◆ TEST() [199/370]

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

Definition at line 149 of file geometry_unittests.cc.

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

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

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

Definition at line 173 of file geometry_unittests.cc.

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

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

## ◆ TEST() [201/370]

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

Definition at line 195 of file geometry_unittests.cc.

195 {
196 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
197 Matrix::MakeRotationZ(Radians{kPiOver4}) *
198 Matrix::MakeScale({2.0, 2.0, 2.0});
199
200 auto result = matrix.Decompose();
201
202 ASSERT_TRUE(result.has_value());
203
204 ASSERT_MATRIX_NEAR(matrix, Matrix{result.value()});
205 }

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

## ◆ TEST() [202/370]

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

Definition at line 1711 of file geometry_unittests.cc.

1711 {
1712 ASSERT_EQ(Color::ToIColor(Color(0, 0, 0, 0)), 0u);
1713 ASSERT_EQ(Color::ToIColor(Color(1.0, 1.0, 1.0, 1.0)), 0xFFFFFFFF);
1714 ASSERT_EQ(Color::ToIColor(Color(0.5, 0.5, 1.0, 1.0)), 0xFF8080FF);
1715 }

References impeller::Color::ToIColor().

## ◆ TEST() [203/370]

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

Definition at line 1067 of file geometry_unittests.cc.

1067 {
1068 Vector3 p(1.5, 2.3, 3.9);
1069 Vector3 result = p.Ceil();
1070 Vector3 expected(2, 3, 4);
1071 ASSERT_VECTOR3_NEAR(result, expected);
1072 }

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

## ◆ TEST() [204/370]

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

Definition at line 1046 of file geometry_unittests.cc.

1046 {
1047 Vector3 p(1.5, 2.3, 3.9);
1048 Vector3 result = p.Floor();
1049 Vector3 expected(1, 2, 3);
1050 ASSERT_VECTOR3_NEAR(result, expected);
1051 }

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

## ◆ TEST() [205/370]

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

Definition at line 1109 of file geometry_unittests.cc.

1109 {
1110 Vector3 p(1, 2, 3);
1111 Vector3 result = p.Lerp({5, 10, 15}, 0.75);
1112 Vector3 expected(4, 8, 12);
1113 ASSERT_VECTOR3_NEAR(result, expected);
1114 }

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

## ◆ TEST() [206/370]

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

Definition at line 1025 of file geometry_unittests.cc.

1025 {
1026 Vector3 p(1, 2, 3);
1027 Vector3 result = p.Max({0, 10, 2});
1028 Vector3 expected(1, 10, 3);
1029 ASSERT_VECTOR3_NEAR(result, expected);
1030 }

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

## ◆ TEST() [207/370]

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

Definition at line 1004 of file geometry_unittests.cc.

1004 {
1005 Vector3 p(1, 2, 3);
1006 Vector3 result = p.Min({0, 10, 2});
1007 Vector3 expected(0, 2, 2);
1008 ASSERT_VECTOR3_NEAR(result, expected);
1009 }

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

## ◆ TEST() [208/370]

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

Definition at line 1663 of file geometry_unittests.cc.

1663 {
1664 {
1665 std::stringstream stream;
1666 Vector3 m;
1667 stream << m;
1668 ASSERT_EQ(stream.str(), "(0, 0, 0)");
1669 }
1670
1671 {
1672 std::stringstream stream;
1673 Vector3 m(1, 2, 3);
1674 stream << m;
1675 ASSERT_EQ(stream.str(), "(1, 2, 3)");
1676 }
1677 }

## ◆ TEST() [209/370]

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

Definition at line 1088 of file geometry_unittests.cc.

1088 {
1089 Vector3 p(1.5, 2.3, 3.9);
1090 Vector3 result = p.Round();
1091 Vector3 expected(2, 2, 4);
1092 ASSERT_VECTOR3_NEAR(result, expected);
1093 }

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

## ◆ TEST() [210/370]

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

Definition at line 1074 of file geometry_unittests.cc.

1074 {
1075 Vector4 p(1.5, 2.3, 3.9, 4.0);
1076 Vector4 result = p.Ceil();
1077 Vector4 expected(2, 3, 4, 4);
1078 ASSERT_VECTOR4_NEAR(result, expected);
1079 }

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

## ◆ TEST() [211/370]

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

Definition at line 1053 of file geometry_unittests.cc.

1053 {
1054 Vector4 p(1.5, 2.3, 3.9, 4.0);
1055 Vector4 result = p.Floor();
1056 Vector4 expected(1, 2, 3, 4);
1057 ASSERT_VECTOR4_NEAR(result, expected);
1058 }

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

## ◆ TEST() [212/370]

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

Definition at line 1116 of file geometry_unittests.cc.

1116 {
1117 Vector4 p(1, 2, 3, 4);
1118 Vector4 result = p.Lerp({5, 10, 15, 20}, 0.75);
1119 Vector4 expected(4, 8, 12, 16);
1120 ASSERT_VECTOR4_NEAR(result, expected);
1121 }

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

## ◆ TEST() [213/370]

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

Definition at line 1032 of file geometry_unittests.cc.

1032 {
1033 Vector4 p(1, 2, 3, 4);
1034 Vector4 result = p.Max({0, 10, 2, 1});
1035 Vector4 expected(1, 10, 3, 4);
1036 ASSERT_VECTOR4_NEAR(result, expected);
1037 }

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

## ◆ TEST() [214/370]

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

Definition at line 1011 of file geometry_unittests.cc.

1011 {
1012 Vector4 p(1, 2, 3, 4);
1013 Vector4 result = p.Min({0, 10, 2, 1});
1014 Vector4 expected(0, 2, 2, 1);
1015 ASSERT_VECTOR4_NEAR(result, expected);
1016 }

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

## ◆ TEST() [215/370]

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

Definition at line 1679 of file geometry_unittests.cc.

1679 {
1680 {
1681 std::stringstream stream;
1682 Vector4 m;
1683 stream << m;
1684 ASSERT_EQ(stream.str(), "(0, 0, 0, 1)");
1685 }
1686
1687 {
1688 std::stringstream stream;
1689 Vector4 m(1, 2, 3, 4);
1690 stream << m;
1691 ASSERT_EQ(stream.str(), "(1, 2, 3, 4)");
1692 }
1693 }

## ◆ TEST() [216/370]

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

Definition at line 1095 of file geometry_unittests.cc.

1095 {
1096 Vector4 p(1.5, 2.3, 3.9, 4.0);
1097 Vector4 result = p.Round();
1098 Vector4 expected(2, 2, 4, 4);
1099 ASSERT_VECTOR4_NEAR(result, expected);
1100 }

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

## ◆ TEST() [217/370]

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

Definition at line 14 of file matrix_unittests.cc.

14 {
15 Matrix x(0.0, 0.0, 0.0, 1.0, //
16 1.0, 0.0, 0.0, 1.0, //
17 0.0, 1.0, 0.0, 1.0, //
18 1.0, 1.0, 0.0, 1.0);
19 Matrix translate = Matrix::MakeTranslation({10, 20, 0});
20 Matrix result = translate * x;
21 EXPECT_TRUE(MatrixNear(result, Matrix(10.0, 20.0, 0.0, 1.0, //
22 11.0, 20.0, 0.0, 1.0, //
23 10.0, 21.0, 0.0, 1.0, //
24 11.0, 21.0, 0.0, 1.0)));
25 }

References impeller::Matrix::MakeTranslation(), and MatrixNear().

## ◆ TEST() [218/370]

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

Definition at line 339 of file path_unittests.cc.

339 {
340 PathBuilder builder;
341 auto path =
342 builder.AddCubicCurve({120, 160}, {25, 200}, {220, 260}, {220, 40})
343 .TakePath();
344 auto box = path.GetBoundingBox();
345 Rect expected = Rect::MakeXYWH(93.9101, 40, 126.09, 158.862);
346 ASSERT_TRUE(box.has_value());
347 ASSERT_RECT_NEAR(box.value_or(Rect::MakeMaximum()), expected);
348 }

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

## ◆ TEST() [219/370]

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

Definition at line 350 of file path_unittests.cc.

350 {
351 PathBuilder builder;
352 builder.AddRoundedRect(Rect::MakeXYWH(10, 10, 300, 300), {50, 50, 50, 50});
353 auto path = builder.TakePath();
354 auto actual = path.GetBoundingBox();
355 Rect expected = Rect::MakeXYWH(10, 10, 300, 300);
356
357 ASSERT_TRUE(actual.has_value());
358 ASSERT_RECT_NEAR(actual.value_or(Rect::MakeMaximum()), expected);
359 }

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

## ◆ TEST() [220/370]

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

Definition at line 457 of file path_unittests.cc.

457 {
458 PathBuilder builder;
459 builder.MoveTo({10, 10});
460 builder.LineTo({20, 20});
461 builder.SetBounds(Rect::MakeLTRB(0, 0, 100, 100));
462 builder.SetConvexity(Convexity::kConvex);
463
464 auto path_a = builder.TakePath(FillType::kOdd);
465 // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
466 auto path_b = path_a;
467
468 EXPECT_EQ(path_a.GetBoundingBox(), path_b.GetBoundingBox());
469 EXPECT_EQ(path_a.GetFillType(), path_b.GetFillType());
470 EXPECT_EQ(path_a.IsConvex(), path_b.IsConvex());
471
472 auto poly_a = path_a.CreatePolyline(1.0);
473 auto poly_b = path_b.CreatePolyline(1.0);
474
475 ASSERT_EQ(poly_a.points->size(), poly_b.points->size());
476 ASSERT_EQ(poly_a.contours.size(), poly_b.contours.size());
477
478 for (auto i = 0u; i < poly_a.points->size(); i++) {
479 EXPECT_EQ((*poly_a.points)[i], (*poly_b.points)[i]);
480 }
481
482 for (auto i = 0u; i < poly_a.contours.size(); i++) {
483 EXPECT_EQ(poly_a.contours[i].start_index, poly_b.contours[i].start_index);
484 EXPECT_EQ(poly_a.contours[i].start_direction,
485 poly_b.contours[i].start_direction);
486 }
487 }

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

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

Definition at line 324 of file path_unittests.cc.

324 {
325 PathBuilder builder;
326 auto path =
327 builder.CubicCurveTo(Point(10, 10), Point(-10, -10), Point(20, 20))
328 .TakePath();
329
330 CubicPathComponent cubic;
331 path.GetCubicComponentAtIndex(1, cubic);
332
333 EXPECT_EQ(cubic.p1, Point(0, 0));
334 EXPECT_EQ(cubic.cp1, Point(10, 10));
335 EXPECT_EQ(cubic.cp2, Point(-10, -10));
336 EXPECT_EQ(cubic.p2, Point(20, 20));
337 }

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

## ◆ TEST() [222/370]

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

Definition at line 15 of file path_unittests.cc.

15 {
16 CubicPathComponent component({10, 10}, {20, 35}, {35, 20}, {40, 40});
17 std::vector<Point> polyline;
18 component.AppendPolylinePoints(1.0f, polyline);
19 ASSERT_NE(polyline.front().x, 10);
20 ASSERT_NE(polyline.front().y, 10);
21 ASSERT_EQ(polyline.back().x, 40);
22 ASSERT_EQ(polyline.back().y, 40);
23 }

References polyline.

## ◆ TEST() [223/370]

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

Definition at line 384 of file path_unittests.cc.

384 {
385 auto path = PathBuilder{}.TakePath();
386 ASSERT_EQ(path.GetComponentCount(), 1u);
387
388 ContourComponent c;
389 path.GetContourComponentAtIndex(0, c);
390 ASSERT_POINT_NEAR(c.destination, Point());
391
392 Path::Polyline polyline = path.CreatePolyline(1.0f);
393 ASSERT_TRUE(polyline.points->empty());
394 ASSERT_TRUE(polyline.contours.empty());
395 }

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

## ◆ TEST() [224/370]

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

Definition at line 361 of file path_unittests.cc.

361 {
362 CubicPathComponent cubic{{11.769268, 252.883148},
363 {-6.2857933, 204.356461},
364 {-4.53997231, 156.552902},
365 {17.0067291, 109.472488}};
366 auto points = cubic.Extrema();
367
368 ASSERT_EQ(points.size(), static_cast<size_t>(3));
369 ASSERT_POINT_NEAR(points[2], cubic.Solve(0.455916));
370 }

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

## ◆ TEST() [225/370]

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

Definition at line 160 of file path_unittests.cc.

160 {
161 Path::Polyline polyline = PathBuilder{}
162 .AddRect(Rect::MakeLTRB(50, 60, 70, 80))
163 .TakePath()
164 .CreatePolyline(1.0f);
165 ASSERT_EQ(polyline.contours.size(), 1u);
166 ASSERT_TRUE(polyline.contours[0].is_closed);
167 ASSERT_EQ(polyline.contours[0].start_index, 0u);
168 ASSERT_EQ(polyline.points->size(), 5u);
169 ASSERT_EQ(polyline.GetPoint(0), Point(50, 60));
170 ASSERT_EQ(polyline.GetPoint(1), Point(70, 60));
171 ASSERT_EQ(polyline.GetPoint(2), Point(70, 80));
172 ASSERT_EQ(polyline.GetPoint(3), Point(50, 80));
173 ASSERT_EQ(polyline.GetPoint(4), Point(50, 60));
174 }

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

## ◆ TEST() [226/370]

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

Definition at line 489 of file path_unittests.cc.

489 {
490 auto test_isolation =
491 [](const std::function<void(PathBuilder & builder)>& mutator,
492 bool will_close, Point mutation_offset, const std::string& label) {
493 PathBuilder builder;
494 builder.MoveTo({10, 10});
495 builder.LineTo({20, 20});
496 builder.LineTo({20, 10});
497
498 auto verify_path = [](const Path& path, bool is_mutated, bool is_closed,
499 Point offset, const std::string& label) {
500 if (is_mutated) {
501 // We can only test the initial state before the mutator did
502 // its work. We have >= 3 components and the first 3 components
503 // will match what we saw before the mutation.
504 EXPECT_GE(path.GetComponentCount(), 3u) << label;
505 } else {
506 EXPECT_EQ(path.GetComponentCount(), 3u) << label;
507 }
508 {
509 ContourComponent contour;
510 EXPECT_TRUE(path.GetContourComponentAtIndex(0, contour)) << label;
511 EXPECT_EQ(contour.destination, offset + Point(10, 10)) << label;
512 EXPECT_EQ(contour.is_closed, is_closed) << label;
513 }
514 {
515 LinearPathComponent line;
516 EXPECT_TRUE(path.GetLinearComponentAtIndex(1, line)) << label;
517 EXPECT_EQ(line.p1, offset + Point(10, 10)) << label;
518 EXPECT_EQ(line.p2, offset + Point(20, 20)) << label;
519 }
520 {
521 LinearPathComponent line;
522 EXPECT_TRUE(path.GetLinearComponentAtIndex(2, line)) << label;
523 EXPECT_EQ(line.p1, offset + Point(20, 20)) << label;
524 EXPECT_EQ(line.p2, offset + Point(20, 10)) << label;
525 }
526 };
527
528 auto path1 = builder.CopyPath();
529 verify_path(path1, false, false, {},
530 "Initial Path1 state before " + label);
531
532 for (int i = 0; i < 10; i++) {
533 auto path = builder.CopyPath();
534 verify_path(
535 path, false, false, {},
536 "Extra CopyPath #" + std::to_string(i + 1) + " for " + label);
537 }
538 mutator(builder);
539 verify_path(path1, false, false, {},
540 "Path1 state after subsequent " + label);
541
542 auto path2 = builder.CopyPath();
543 verify_path(path1, false, false, {},
544 "Path1 state after subsequent " + label + " and CopyPath");
545 verify_path(path2, true, will_close, mutation_offset,
546 "Initial Path2 state with subsequent " + label);
547 };
548
549 test_isolation(
550 [](PathBuilder& builder) { //
551 builder.SetConvexity(Convexity::kConvex);
552 },
553 false, {}, "SetConvex");
554
555 test_isolation(
556 [](PathBuilder& builder) { //
557 builder.SetConvexity(Convexity::kUnknown);
558 },
559 false, {}, "SetUnknownConvex");
560
561 test_isolation(
562 [](PathBuilder& builder) { //
563 builder.Close();
564 },
565 true, {}, "Close");
566
567 test_isolation(
568 [](PathBuilder& builder) {
569 builder.MoveTo({20, 30}, false);
570 },
571 false, {}, "Absolute MoveTo");
572
573 test_isolation(
574 [](PathBuilder& builder) {
575 builder.MoveTo({20, 30}, true);
576 },
577 false, {}, "Relative MoveTo");
578
579 test_isolation(
580 [](PathBuilder& builder) {
581 builder.LineTo({20, 30}, false);
582 },
583 false, {}, "Absolute LineTo");
584
585 test_isolation(
586 [](PathBuilder& builder) {
587 builder.LineTo({20, 30}, true);
588 },
589 false, {}, "Relative LineTo");
590
591 test_isolation(
592 [](PathBuilder& builder) { //
593 builder.HorizontalLineTo(100, false);
594 },
595 false, {}, "Absolute HorizontalLineTo");
596
597 test_isolation(
598 [](PathBuilder& builder) { //
599 builder.HorizontalLineTo(100, true);
600 },
601 false, {}, "Relative HorizontalLineTo");
602
603 test_isolation(
604 [](PathBuilder& builder) { //
605 builder.VerticalLineTo(100, false);
606 },
607 false, {}, "Absolute VerticalLineTo");
608
609 test_isolation(
610 [](PathBuilder& builder) { //
611 builder.VerticalLineTo(100, true);
612 },
613 false, {}, "Relative VerticalLineTo");
614
615 test_isolation(
616 [](PathBuilder& builder) {
617 builder.QuadraticCurveTo({20, 30}, {30, 20}, false);
618 },
619 false, {}, "Absolute QuadraticCurveTo");
620
621 test_isolation(
622 [](PathBuilder& builder) {
623 builder.QuadraticCurveTo({20, 30}, {30, 20}, true);
624 },
625 false, {}, "Relative QuadraticCurveTo");
626
627 test_isolation(
628 [](PathBuilder& builder) {
629 builder.CubicCurveTo({20, 30}, {30, 20}, {30, 30}, false);
630 },
631 false, {}, "Absolute CubicCurveTo");
632
633 test_isolation(
634 [](PathBuilder& builder) {
635 builder.CubicCurveTo({20, 30}, {30, 20}, {30, 30}, true);
636 },
637 false, {}, "Relative CubicCurveTo");
638
639 test_isolation(
640 [](PathBuilder& builder) {
641 builder.AddLine({100, 100}, {150, 100});
642 },
643 false, {}, "AddLine");
644
645 test_isolation(
646 [](PathBuilder& builder) {
647 builder.AddRect(Rect::MakeLTRB(100, 100, 120, 120));
648 },
649 false, {}, "AddRect");
650
651 test_isolation(
652 [](PathBuilder& builder) {
653 builder.AddOval(Rect::MakeLTRB(100, 100, 120, 120));
654 },
655 false, {}, "AddOval");
656
657 test_isolation(
658 [](PathBuilder& builder) {
659 builder.AddCircle({100, 100}, 20);
660 },
661 false, {}, "AddCircle");
662
663 test_isolation(
664 [](PathBuilder& builder) {
665 builder.AddArc(Rect::MakeLTRB(100, 100, 120, 120), Degrees(10),
666 Degrees(170));
667 },
668 false, {}, "AddArc");
669
670 test_isolation(
671 [](PathBuilder& builder) {
672 builder.AddQuadraticCurve({100, 100}, {150, 100}, {150, 150});
673 },
674 false, {}, "AddQuadraticCurve");
675
676 test_isolation(
677 [](PathBuilder& builder) {
678 builder.AddCubicCurve({100, 100}, {150, 100}, {100, 150}, {150, 150});
679 },
680 false, {}, "AddCubicCurve");
681
682 test_isolation(
683 [](PathBuilder& builder) {
684 builder.Shift({23, 42});
685 },
686 false, {23, 42}, "Shift");
687 }

References impeller::PathBuilder::AddArc(), impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddLine(), impeller::PathBuilder::AddOval(), impeller::PathBuilder::AddQuadraticCurve(), impeller::PathBuilder::AddRect(), impeller::PathBuilder::Close(), impeller::PathBuilder::CopyPath(), impeller::PathBuilder::CubicCurveTo(), impeller::ContourComponent::destination, impeller::Path::GetComponentCount(), impeller::Path::GetContourComponentAtIndex(), impeller::Path::GetLinearComponentAtIndex(), impeller::PathBuilder::HorizontalLineTo(), impeller::ContourComponent::is_closed, impeller::kConvex, 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() [227/370]

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

Definition at line 44 of file path_unittests.cc.

44 {
45 // Closed shapes.
46 {
47 Path path = PathBuilder{}.AddCircle({100, 100}, 50).TakePath();
48 ContourComponent contour;
49 path.GetContourComponentAtIndex(0, contour);
50 ASSERT_POINT_NEAR(contour.destination, Point(100, 50));
51 ASSERT_TRUE(contour.is_closed);
52 }
53
54 {
55 Path path =
56 PathBuilder{}.AddOval(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
57 ContourComponent contour;
58 path.GetContourComponentAtIndex(0, contour);
59 ASSERT_POINT_NEAR(contour.destination, Point(150, 100));
60 ASSERT_TRUE(contour.is_closed);
61 }
62
63 {
64 Path path =
65 PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
66 ContourComponent contour;
67 path.GetContourComponentAtIndex(0, contour);
68 ASSERT_POINT_NEAR(contour.destination, Point(100, 100));
69 ASSERT_TRUE(contour.is_closed);
70 }
71
72 {
73 Path path = PathBuilder{}
74 .AddRoundedRect(Rect::MakeXYWH(100, 100, 100, 100), 10)
75 .TakePath();
76 ContourComponent contour;
77 path.GetContourComponentAtIndex(0, contour);
78 ASSERT_POINT_NEAR(contour.destination, Point(110, 100));
79 ASSERT_TRUE(contour.is_closed);
80 }
81
82 {
83 Path path =
84 PathBuilder{}
85 .AddRoundedRect(Rect::MakeXYWH(100, 100, 100, 100), Size(10, 20))
86 .TakePath();
87 ContourComponent contour;
88 path.GetContourComponentAtIndex(0, contour);
89 ASSERT_POINT_NEAR(contour.destination, Point(110, 100));
90 ASSERT_TRUE(contour.is_closed);
91 }
92
93 // Open shapes.
94 {
95 Point p(100, 100);
96 Path path = PathBuilder{}.AddLine(p, {200, 100}).TakePath();
97 ContourComponent contour;
98 path.GetContourComponentAtIndex(0, contour);
99 ASSERT_POINT_NEAR(contour.destination, p);
100 ASSERT_FALSE(contour.is_closed);
101 }
102
103 {
104 Path path =
105 PathBuilder{}
106 .AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
107 .TakePath();
108 ContourComponent contour;
109 path.GetContourComponentAtIndex(0, contour);
110 ASSERT_POINT_NEAR(contour.destination, Point(100, 100));
111 ASSERT_FALSE(contour.is_closed);
112 }
113
114 {
115 Path path = PathBuilder{}
116 .AddQuadraticCurve({100, 100}, {100, 50}, {200, 100})
117 .TakePath();
118 ContourComponent contour;
119 path.GetContourComponentAtIndex(0, contour);
120 ASSERT_POINT_NEAR(contour.destination, Point(100, 100));
121 ASSERT_FALSE(contour.is_closed);
122 }
123 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddLine(), impeller::PathBuilder::AddOval(), impeller::PathBuilder::AddQuadraticCurve(), impeller::PathBuilder::AddRect(), impeller::PathBuilder::AddRoundedRect(), ASSERT_POINT_NEAR, impeller::ContourComponent::destination, impeller::Path::GetContourComponentAtIndex(), impeller::ContourComponent::is_closed, impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [228/370]

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

Definition at line 268 of file path_unittests.cc.

268 {
269 PathBuilder builder;
270 auto path_1 = builder.AddLine({0, 0}, {1, 1}).TakePath();
271
272 ASSERT_EQ(path_1.GetBoundingBox().value_or(Rect::MakeMaximum()),
273 Rect::MakeLTRB(0, 0, 1, 1));
274
275 auto path_2 = builder.AddLine({-1, -1}, {1, 1}).TakePath();
276
277 // Verify that PathBuilder recomputes the bounds.
278 ASSERT_EQ(path_2.GetBoundingBox().value_or(Rect::MakeMaximum()),
279 Rect::MakeLTRB(-1, -1, 1, 1));
280
281 // PathBuilder can set the bounds to whatever it wants
282 auto path_3 = builder.AddLine({0, 0}, {1, 1})
283 .SetBounds(Rect::MakeLTRB(0, 0, 100, 100))
284 .TakePath();
285
286 ASSERT_EQ(path_3.GetBoundingBox().value_or(Rect::MakeMaximum()),
287 Rect::MakeLTRB(0, 0, 100, 100));
288 }

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

## ◆ TEST() [229/370]

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

Definition at line 25 of file path_unittests.cc.

25 {
26 PathBuilder builder;
27 builder.MoveTo({10, 10});
28 builder.LineTo({20, 20});
29 builder.LineTo({30, 30});
30 builder.MoveTo({40, 40});
31 builder.LineTo({50, 50});
32
33 auto polyline = builder.TakePath().CreatePolyline(1.0f);
34
35 ASSERT_EQ(polyline.contours.size(), 2u);
36 ASSERT_EQ(polyline.points->size(), 5u);
37 ASSERT_EQ(polyline.GetPoint(0).x, 10);
38 ASSERT_EQ(polyline.GetPoint(1).x, 20);
39 ASSERT_EQ(polyline.GetPoint(2).x, 30);
40 ASSERT_EQ(polyline.GetPoint(3).x, 40);
41 ASSERT_EQ(polyline.GetPoint(4).x, 50);
42 }

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

## ◆ TEST() [230/370]

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

Definition at line 125 of file path_unittests.cc.

125 {
126 Path::Polyline polyline = PathBuilder{}
127 .AddLine({100, 100}, {200, 100})
128 .MoveTo({100, 200})
129 .LineTo({150, 250})
130 .LineTo({200, 200})
131 .Close()
132 .TakePath()
133 .CreatePolyline(1.0f);
134 ASSERT_EQ(polyline.points->size(), 6u);
135 ASSERT_EQ(polyline.contours.size(), 2u);
136 ASSERT_EQ(polyline.contours[0].is_closed, false);
137 ASSERT_EQ(polyline.contours[0].start_index, 0u);
138 ASSERT_EQ(polyline.contours[1].is_closed, true);
139 ASSERT_EQ(polyline.contours[1].start_index, 2u);
140 }

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

## ◆ TEST() [231/370]

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

Definition at line 372 of file path_unittests.cc.

372 {
373 PathBuilder builder;
374 // Straight diagonal line.
375 builder.AddCubicCurve({0, 1}, {2, 3}, {4, 5}, {6, 7});
376 auto path = builder.TakePath();
377 auto actual = path.GetBoundingBox();
378 auto expected = Rect::MakeLTRB(0, 1, 6, 7);
379
380 ASSERT_TRUE(actual.has_value());
381 ASSERT_RECT_NEAR(actual.value_or(Rect::MakeMaximum()), expected);
382 }

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

## ◆ TEST() [232/370]

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

Definition at line 290 of file path_unittests.cc.

290 {
291 PathBuilder builder;
292 auto path = builder.HorizontalLineTo(10).TakePath();
293
294 LinearPathComponent linear;
295 path.GetLinearComponentAtIndex(1, linear);
296
297 EXPECT_EQ(linear.p1, Point(0, 0));
298 EXPECT_EQ(linear.p2, Point(10, 0));
299 }

References impeller::PathBuilder::HorizontalLineTo(), impeller::LinearPathComponent::p1, impeller::LinearPathComponent::p2, and impeller::PathBuilder::TakePath().

## ◆ TEST() [233/370]

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

Definition at line 176 of file path_unittests.cc.

176 {
177 Path::Polyline polyline =
178 PathBuilder{}
179 .MoveTo({50, 50})
180 .LineTo({50, 50}) // Insert duplicate at beginning of contour.
181 .LineTo({100, 50})
182 .LineTo({100, 50}) // Insert duplicate at contour join.
183 .LineTo({100, 100})
184 .Close() // Implicitly insert duplicate {50, 50} across contours.
185 .LineTo({0, 50})
186 .LineTo({0, 100})
187 .LineTo({0, 100}) // Insert duplicate at end of contour.
188 .TakePath()
189 .CreatePolyline(1.0f);
190 ASSERT_EQ(polyline.contours.size(), 2u);
191 ASSERT_EQ(polyline.contours[0].start_index, 0u);
192 ASSERT_TRUE(polyline.contours[0].is_closed);
193 ASSERT_EQ(polyline.contours[1].start_index, 4u);
194 ASSERT_FALSE(polyline.contours[1].is_closed);
195 ASSERT_EQ(polyline.points->size(), 7u);
196 ASSERT_EQ(polyline.GetPoint(0), Point(50, 50));
197 ASSERT_EQ(polyline.GetPoint(1), Point(100, 50));
198 ASSERT_EQ(polyline.GetPoint(2), Point(100, 100));
199 ASSERT_EQ(polyline.GetPoint(3), Point(50, 50));
200 ASSERT_EQ(polyline.GetPoint(4), Point(50, 50));
201 ASSERT_EQ(polyline.GetPoint(5), Point(0, 50));
202 ASSERT_EQ(polyline.GetPoint(6), Point(0, 100));
203 }

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

## ◆ TEST() [234/370]

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

Definition at line 232 of file path_unittests.cc.

232 {
233 PathBuilder builder{};
234 auto path =
235 builder.AddLine(Point(0, 0), Point(10, 10))
236 .AddQuadraticCurve(Point(10, 10), Point(15, 15), Point(20, 20))
237 .AddCubicCurve(Point(20, 20), Point(25, 25), Point(-5, -5),
238 Point(30, 30))
239 .Close()
240 .Shift(Point(1, 1))
241 .TakePath();
242
243 ContourComponent contour;
244 LinearPathComponent linear;
245 QuadraticPathComponent quad;
246 CubicPathComponent cubic;
247
248 ASSERT_TRUE(path.GetContourComponentAtIndex(0, contour));
249 ASSERT_TRUE(path.GetLinearComponentAtIndex(1, linear));
250 ASSERT_TRUE(path.GetQuadraticComponentAtIndex(3, quad));
251 ASSERT_TRUE(path.GetCubicComponentAtIndex(5, cubic));
252
253 EXPECT_EQ(contour.destination, Point(1, 1));
254
255 EXPECT_EQ(linear.p1, Point(1, 1));
256 EXPECT_EQ(linear.p2, Point(11, 11));
257
258 EXPECT_EQ(quad.cp, Point(16, 16));
259 EXPECT_EQ(quad.p1, Point(11, 11));
260 EXPECT_EQ(quad.p2, Point(21, 21));
261
262 EXPECT_EQ(cubic.cp1, Point(26, 26));
263 EXPECT_EQ(cubic.cp2, Point(-4, -4));
264 EXPECT_EQ(cubic.p1, Point(21, 21));
265 EXPECT_EQ(cubic.p2, Point(31, 31));
266 }

References impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddLine(), impeller::PathBuilder::AddQuadraticCurve(), impeller::PathBuilder::Close(), impeller::QuadraticPathComponent::cp, impeller::CubicPathComponent::cp1, impeller::CubicPathComponent::cp2, impeller::ContourComponent::destination, 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() [235/370]

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

Definition at line 301 of file path_unittests.cc.

301 {
302 PathBuilder builder;
303 auto path = builder.VerticalLineTo(10).TakePath();
304
305 LinearPathComponent linear;
306 path.GetLinearComponentAtIndex(1, linear);
307
308 EXPECT_EQ(linear.p1, Point(0, 0));
309 EXPECT_EQ(linear.p2, Point(0, 10));
310 }

References impeller::LinearPathComponent::p1, impeller::LinearPathComponent::p2, impeller::PathBuilder::TakePath(), and impeller::PathBuilder::VerticalLineTo().

## ◆ TEST() [236/370]

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

Definition at line 205 of file path_unittests.cc.

205 {
206 auto point_buffer = std::make_unique<std::vector<Point>>();
207 auto point_buffer_address = reinterpret_cast<uintptr_t>(point_buffer.get());
208 Path::Polyline polyline =
209 PathBuilder{}
210 .MoveTo({50, 50})
211 .LineTo({100, 100})
212 .TakePath()
213 .CreatePolyline(
214 1.0f, std::move(point_buffer),
215 [point_buffer_address](
216 Path::Polyline::PointBufferPtr point_buffer) {
217 ASSERT_EQ(point_buffer->size(), 0u);
218 ASSERT_EQ(point_buffer_address,
219 reinterpret_cast<uintptr_t>(point_buffer.get()));
220 });
221 }

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

## ◆ TEST() [237/370]

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

Definition at line 223 of file path_unittests.cc.

223 {
224 EXPECT_DEATH_IF_SUPPORTED(PathBuilder{}
225 .MoveTo({50, 50})
226 .LineTo({100, 100})
227 .TakePath()
228 .CreatePolyline(1.0f, nullptr),
229 "");
230 }

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

## ◆ TEST() [238/370]

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

Definition at line 142 of file path_unittests.cc.

142 {
143 Path::Polyline polyline = PathBuilder{}
144 .AddLine({100, 100}, {200, 100})
145 .MoveTo({100, 200})
146 .LineTo({150, 250})
147 .LineTo({200, 200})
148 .Close()
149 .TakePath()
150 .CreatePolyline(1.0f);
151 size_t a1, a2, b1, b2;
152 std::tie(a1, a2) = polyline.GetContourPointBounds(0);
153 std::tie(b1, b2) = polyline.GetContourPointBounds(1);
154 ASSERT_EQ(a1, 0u);
155 ASSERT_EQ(a2, 2u);
156 ASSERT_EQ(b1, 2u);
157 ASSERT_EQ(b2, 6u);
158 }

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

## ◆ TEST() [239/370]

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

Definition at line 312 of file path_unittests.cc.

312 {
313 PathBuilder builder;
314 auto path = builder.QuadraticCurveTo(Point(10, 10), Point(20, 20)).TakePath();
315
316 QuadraticPathComponent quad;
317 path.GetQuadraticComponentAtIndex(1, quad);
318
319 EXPECT_EQ(quad.p1, Point(0, 0));
320 EXPECT_EQ(quad.cp, Point(10, 10));
321 EXPECT_EQ(quad.p2, Point(20, 20));
322 }

References impeller::QuadraticPathComponent::cp, impeller::QuadraticPathComponent::p1, impeller::QuadraticPathComponent::p2, impeller::PathBuilder::QuadraticCurveTo(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [240/370]

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

Definition at line 397 of file path_unittests.cc.

397 {
398 PathBuilder builder;
399
400 auto path = builder.AddLine({0, 0}, {100, 100})
401 .AddQuadraticCurve({100, 100}, {200, 200}, {300, 300})
402 .AddCubicCurve({300, 300}, {400, 400}, {500, 500}, {600, 600})
403 .TakePath();
404
405 ASSERT_EQ(path.GetComponentCount(), 6u);
406 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 1u);
407 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kQuadratic), 1u);
408 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kCubic), 1u);
409 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 3u);
410
411 path.EnumerateComponents(
412 [](size_t index, const LinearPathComponent& linear) {
413 Point p1(0, 0);
414 Point p2(100, 100);
415 ASSERT_EQ(index, 1u);
416 ASSERT_EQ(linear.p1, p1);
417 ASSERT_EQ(linear.p2, p2);
418 },
419 [](size_t index, const QuadraticPathComponent& quad) {
420 Point p1(100, 100);
421 Point cp(200, 200);
422 Point p2(300, 300);
423 ASSERT_EQ(index, 3u);
424 ASSERT_EQ(quad.p1, p1);
425 ASSERT_EQ(quad.cp, cp);
426 ASSERT_EQ(quad.p2, p2);
427 },
428 [](size_t index, const CubicPathComponent& cubic) {
429 Point p1(300, 300);
430 Point cp1(400, 400);
431 Point cp2(500, 500);
432 Point p2(600, 600);
433 ASSERT_EQ(index, 5u);
434 ASSERT_EQ(cubic.p1, p1);
435 ASSERT_EQ(cubic.cp1, cp1);
436 ASSERT_EQ(cubic.cp2, cp2);
437 ASSERT_EQ(cubic.p2, p2);
438 },
439 [](size_t index, const ContourComponent& contour) {
440 // There is an initial countour added for each curve.
441 if (index == 0u) {
442 Point p1(0, 0);
443 ASSERT_EQ(contour.destination, p1);
444 } else if (index == 2u) {
445 Point p1(100, 100);
446 ASSERT_EQ(contour.destination, p1);
447 } else if (index == 4u) {
448 Point p1(300, 300);
449 ASSERT_EQ(contour.destination, p1);
450 } else {
451 ASSERT_FALSE(true);
452 }
453 ASSERT_FALSE(contour.is_closed);
454 });
455 }

References impeller::PathBuilder::AddLine(), impeller::Path::kContour, impeller::Path::kCubic, impeller::Path::kLinear, impeller::Path::kQuadratic, impeller::LinearPathComponent::p1, and impeller::LinearPathComponent::p2.

## ◆ TEST() [241/370]

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

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 }

## ◆ TEST() [243/370]

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 }

## ◆ TEST() [244/370]

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

Definition at line 1271 of file rect_unittests.cc.

1271 {
1272 auto rect1 =
1273 Rect::MakeXYWH(472.599945f, 440.999969f, 1102.80005f, 654.000061f);
1274 auto rect2 = Rect::MakeXYWH(724.f, 618.f, 600.f, 300.f);
1275 EXPECT_TRUE(rect1.Contains(rect2));
1276 }

References impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [245/370]

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

Definition at line 854 of file rect_unittests.cc.

854 {
855 IRect rect = IRect::MakeLTRB(50, 50, 100, 100);
856
857 auto test = [&rect](int64_t l, int64_t t, int64_t r, int64_t b,
858 const std::string& label) {
859 EXPECT_FALSE(IRect::MakeLTRB(l, b, r, t).IntersectsWithRect(rect))
860 << label << " with Top/Bottom swapped";
861 EXPECT_FALSE(IRect::MakeLTRB(r, b, l, t).IntersectsWithRect(rect))
862 << label << " with Left/Right swapped";
863 EXPECT_FALSE(IRect::MakeLTRB(r, t, l, b).IntersectsWithRect(rect))
864 << label << " with all sides swapped";
865 };
866
867 test(20, 20, 30, 30, "Above and Left");
868 test(70, 20, 80, 30, "Above");
869 test(120, 20, 130, 30, "Above and Right");
870 test(120, 70, 130, 80, "Right");
871 test(120, 120, 130, 130, "Below and Right");
872 test(70, 120, 80, 130, "Below");
873 test(20, 120, 30, 130, "Below and Left");
874 test(20, 70, 30, 80, "Left");
875
876 test(70, 70, 80, 80, "Inside");
877
878 test(40, 70, 60, 80, "Straddling Left");
879 test(70, 40, 80, 60, "Straddling Top");
880 test(90, 70, 110, 80, "Straddling Right");
881 test(70, 90, 80, 110, "Straddling Bottom");
882 }

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

## ◆ TEST() [246/370]

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

Definition at line 824 of file rect_unittests.cc.

824 {
825 Rect rect = Rect::MakeLTRB(50, 50, 100, 100);
826
827 auto test = [&rect](Scalar l, Scalar t, Scalar r, Scalar b,
828 const std::string& label) {
829 EXPECT_FALSE(Rect::MakeLTRB(l, b, r, t).IntersectsWithRect(rect))
830 << label << " with Top/Bottom swapped";
831 EXPECT_FALSE(Rect::MakeLTRB(r, b, l, t).IntersectsWithRect(rect))
832 << label << " with Left/Right swapped";
833 EXPECT_FALSE(Rect::MakeLTRB(r, t, l, b).IntersectsWithRect(rect))
834 << label << " with all sides swapped";
835 };
836
837 test(20, 20, 30, 30, "Above and Left");
838 test(70, 20, 80, 30, "Above");
839 test(120, 20, 130, 30, "Above and Right");
840 test(120, 70, 130, 80, "Right");
841 test(120, 120, 130, 130, "Below and Right");
842 test(70, 120, 80, 130, "Below");
843 test(20, 120, 30, 130, "Below and Left");
844 test(20, 70, 30, 80, "Left");
845
846 test(70, 70, 80, 80, "Inside");
847
848 test(40, 70, 60, 80, "Straddling Left");
849 test(70, 40, 80, 60, "Straddling Top");
850 test(90, 70, 110, 80, "Straddling Right");
851 test(70, 90, 80, 110, "Straddling Bottom");
852 }

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

## ◆ TEST() [247/370]

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

Definition at line 1194 of file rect_unittests.cc.

1194 {
1195 EXPECT_EQ(Rect::MakeXYWH(10, 30, 20, 20).GetCenter(), Point(20, 40));
1196 EXPECT_EQ(Rect::MakeXYWH(10, 30, 20, 19).GetCenter(), Point(20, 39.5));
1197 EXPECT_EQ(Rect::MakeMaximum().GetCenter(), Point(0, 0));
1198
1199 // Note that we expect a Point as the answer from an IRect
1200 EXPECT_EQ(IRect::MakeXYWH(10, 30, 20, 20).GetCenter(), Point(20, 40));
1201 EXPECT_EQ(IRect::MakeXYWH(10, 30, 20, 19).GetCenter(), Point(20, 39.5));
1202 EXPECT_EQ(IRect::MakeMaximum().GetCenter(), Point(0, 0));
1203 }

References impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< int64_t >::MakeMaximum(), impeller::TRect< int64_t >::MakeXYWH(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [248/370]

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

Definition at line 980 of file rect_unittests.cc.

980 {
981 EXPECT_EQ(IRect::MakeXYWH(0, 0, 100, 200).Area(), 20000);
982 EXPECT_EQ(IRect::MakeXYWH(10, 20, 100, 200).Area(), 20000);
983 EXPECT_EQ(IRect::MakeXYWH(0, 0, 200, 100).Area(), 20000);
984 EXPECT_EQ(IRect::MakeXYWH(10, 20, 200, 100).Area(), 20000);
985 EXPECT_EQ(IRect::MakeXYWH(0, 0, 100, 100).Area(), 10000);
986 EXPECT_EQ(IRect::MakeXYWH(10, 20, 100, 100).Area(), 10000);
987 }

References impeller::TRect< int64_t >::MakeXYWH().

## ◆ TEST() [249/370]

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

Definition at line 2193 of file rect_unittests.cc.

2193 {
2194 auto check_empty_flips = [](const IRect& rect, const IPoint& point,
2195 const std::string& label) {
2196 ASSERT_FALSE(rect.IsEmpty());
2197
2198 EXPECT_FALSE(flip_lr(rect).Contains(point)) << label;
2199 EXPECT_FALSE(flip_tb(rect).Contains(point)) << label;
2200 EXPECT_FALSE(flip_lrtb(rect).Contains(point)) << label;
2201 };
2202
2203 auto test_inside = [&check_empty_flips](const IRect& rect,
2204 const IPoint& point) {
2205 ASSERT_FALSE(rect.IsEmpty()) << rect;
2206
2207 std::stringstream stream;
2208 stream << rect << " contains " << point;
2209 auto label = stream.str();
2210
2211 EXPECT_TRUE(rect.Contains(point)) << label;
2212 check_empty_flips(rect, point, label);
2213 };
2214
2215 auto test_outside = [&check_empty_flips](const IRect& rect,
2216 const IPoint& point) {
2217 ASSERT_FALSE(rect.IsEmpty()) << rect;
2218
2219 std::stringstream stream;
2220 stream << rect << " contains " << point;
2221 auto label = stream.str();
2222
2223 EXPECT_FALSE(rect.Contains(point)) << label;
2224 check_empty_flips(rect, point, label);
2225 };
2226
2227 {
2228 // Origin is inclusive
2229 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2230 auto p = IPoint(100, 100);
2231
2232 test_inside(r, p);
2233 }
2234 {
2235 // Size is exclusive
2236 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2237 auto p = IPoint(200, 200);
2238
2239 test_outside(r, p);
2240 }
2241 {
2242 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2243 auto p = IPoint(99, 99);
2244
2245 test_outside(r, p);
2246 }
2247 {
2248 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2249 auto p = IPoint(199, 199);
2250
2251 test_inside(r, p);
2252 }
2253
2254 {
2255 auto r = IRect::MakeMaximum();
2256 auto p = IPoint(199, 199);
2257
2258 test_inside(r, p);
2259 }
2260 }

References impeller::TRect< T >::Contains(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< int64_t >::MakeMaximum(), and impeller::TRect< int64_t >::MakeXYWH().

## ◆ TEST() [250/370]

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

Definition at line 2377 of file rect_unittests.cc.

2377 {
2378 auto check_empty_flips = [](const IRect& a, const IRect& b,
2379 const std::string& label) {
2380 ASSERT_FALSE(a.IsEmpty());
2381 // test b rects are allowed to have 0 w/h, but not be backwards
2382 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2383
2384 // unflipped a vs flipped (empty) b yields true
2385 EXPECT_TRUE(a.Contains(flip_lr(b))) << label;
2386 EXPECT_TRUE(a.Contains(flip_tb(b))) << label;
2387 EXPECT_TRUE(a.Contains(flip_lrtb(b))) << label;
2388
2389 // flipped (empty) a vs unflipped b yields false
2390 EXPECT_FALSE(flip_lr(a).Contains(b)) << label;
2391 EXPECT_FALSE(flip_tb(a).Contains(b)) << label;
2392 EXPECT_FALSE(flip_lrtb(a).Contains(b)) << label;
2393
2394 // flipped (empty) a vs flipped (empty) b yields empty
2395 EXPECT_FALSE(flip_lr(a).Contains(flip_lr(b))) << label;
2396 EXPECT_FALSE(flip_tb(a).Contains(flip_tb(b))) << label;
2397 EXPECT_FALSE(flip_lrtb(a).Contains(flip_lrtb(b))) << label;
2398 };
2399
2400 auto test_inside = [&check_empty_flips](const IRect& a, const IRect& b) {
2401 ASSERT_FALSE(a.IsEmpty()) << a;
2402 // test b rects are allowed to have 0 w/h, but not be backwards
2403 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2404
2405 std::stringstream stream;
2406 stream << a << " contains " << b;
2407 auto label = stream.str();
2408
2409 EXPECT_TRUE(a.Contains(b)) << label;
2410 check_empty_flips(a, b, label);
2411 };
2412
2413 auto test_not_inside = [&check_empty_flips](const IRect& a, const IRect& b) {
2414 ASSERT_FALSE(a.IsEmpty()) << a;
2415 // If b was empty, it would be contained and should not be tested with
2416 // this function - use |test_inside| instead.
2417 ASSERT_FALSE(b.IsEmpty()) << b;
2418
2419 std::stringstream stream;
2420 stream << a << " contains " << b;
2421 auto label = stream.str();
2422
2423 EXPECT_FALSE(a.Contains(b)) << label;
2424 check_empty_flips(a, b, label);
2425 };
2426
2427 {
2428 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2429
2430 test_inside(a, a);
2431 }
2432 {
2433 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2434 auto b = IRect::MakeXYWH(0, 0, 0, 0);
2435
2436 test_inside(a, b);
2437 }
2438 {
2439 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2440 auto b = IRect::MakeXYWH(150, 150, 20, 20);
2441
2442 test_inside(a, b);
2443 }
2444 {
2445 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2446 auto b = IRect::MakeXYWH(150, 150, 100, 100);
2447
2448 test_not_inside(a, b);
2449 }
2450 {
2451 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2452 auto b = IRect::MakeXYWH(50, 50, 100, 100);
2453
2454 test_not_inside(a, b);
2455 }
2456 {
2457 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2458 auto b = IRect::MakeXYWH(0, 0, 300, 300);
2459
2460 test_not_inside(a, b);
2461 }
2462 {
2463 auto a = IRect::MakeMaximum();
2464 auto b = IRect::MakeXYWH(0, 0, 300, 300);
2465
2466 test_inside(a, b);
2467 }
2468 }

References impeller::saturated::b, impeller::TRect< T >::Contains(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< int64_t >::MakeMaximum(), and impeller::TRect< int64_t >::MakeXYWH().

## ◆ TEST() [251/370]

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

Definition at line 641 of file rect_unittests.cc.

641 {
642 IRect rect = IRect::MakeLTRB(5, 10, 20, 25);
643 IRect copy = rect;
644
645 EXPECT_EQ(rect, copy);
646 EXPECT_EQ(copy.GetLeft(), 5);
647 EXPECT_EQ(copy.GetTop(), 10);
648 EXPECT_EQ(copy.GetRight(), 20);
649 EXPECT_EQ(copy.GetBottom(), 25);
650 EXPECT_EQ(copy.GetX(), 5);
651 EXPECT_EQ(copy.GetY(), 10);
652 EXPECT_EQ(copy.GetWidth(), 15);
653 EXPECT_EQ(copy.GetHeight(), 15);
654 EXPECT_FALSE(copy.IsEmpty());
655 }

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< int64_t >::MakeLTRB().

## ◆ TEST() [252/370]

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

Definition at line 2622 of file rect_unittests.cc.

2622 {
2623 IRect cull_rect = IRect::MakeLTRB(20, 20, 40, 40);
2624
2625 auto check_empty_flips = [&cull_rect](const IRect& diff_rect,
2626 const std::string& label) {
2627 EXPECT_FALSE(diff_rect.IsEmpty());
2628 EXPECT_FALSE(cull_rect.IsEmpty());
2629
2630 // unflipped cull_rect vs flipped(empty) diff_rect
2631 // == cull_rect
2632 EXPECT_TRUE(cull_rect.Cutout(flip_lr(diff_rect)).has_value()) << label;
2633 EXPECT_EQ(cull_rect.Cutout(flip_lr(diff_rect)), cull_rect) << label;
2634 EXPECT_TRUE(cull_rect.Cutout(flip_tb(diff_rect)).has_value()) << label;
2635 EXPECT_EQ(cull_rect.Cutout(flip_tb(diff_rect)), cull_rect) << label;
2636 EXPECT_TRUE(cull_rect.Cutout(flip_lrtb(diff_rect)).has_value()) << label;
2637 EXPECT_EQ(cull_rect.Cutout(flip_lrtb(diff_rect)), cull_rect) << label;
2638
2639 // flipped(empty) cull_rect vs flipped(empty) diff_rect
2640 // == empty
2641 EXPECT_FALSE(flip_lr(cull_rect).Cutout(diff_rect).has_value()) << label;
2642 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(diff_rect), IRect()) << label;
2643 EXPECT_FALSE(flip_tb(cull_rect).Cutout(diff_rect).has_value()) << label;
2644 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(diff_rect), IRect()) << label;
2645 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(diff_rect).has_value()) << label;
2646 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(diff_rect), IRect()) << label;
2647
2648 // flipped(empty) cull_rect vs unflipped diff_rect
2649 // == empty
2650 EXPECT_FALSE(flip_lr(cull_rect).Cutout(flip_lr(diff_rect)).has_value())
2651 << label;
2652 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(flip_lr(diff_rect)), IRect())
2653 << label;
2654 EXPECT_FALSE(flip_tb(cull_rect).Cutout(flip_tb(diff_rect)).has_value())
2655 << label;
2656 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(flip_tb(diff_rect)), IRect())
2657 << label;
2658 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(flip_lrtb(diff_rect)).has_value())
2659 << label;
2660 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(flip_lrtb(diff_rect)), IRect())
2661 << label;
2662 };
2663
2664 auto non_reducing = [&cull_rect, &check_empty_flips](
2665 const IRect& diff_rect, const std::string& label) {
2666 EXPECT_EQ(cull_rect.Cutout(diff_rect), cull_rect) << label;
2667 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), cull_rect) << label;
2668 check_empty_flips(diff_rect, label);
2669 };
2670
2671 auto reducing = [&cull_rect, &check_empty_flips](const IRect& diff_rect,
2672 const IRect& result_rect,
2673 const std::string& label) {
2674 EXPECT_TRUE(!result_rect.IsEmpty());
2675 EXPECT_EQ(cull_rect.Cutout(diff_rect), result_rect) << label;
2676 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), result_rect) << label;
2677 check_empty_flips(diff_rect, label);
2678 };
2679
2680 auto emptying = [&cull_rect, &check_empty_flips](const IRect& diff_rect,
2681 const std::string& label) {
2682 EXPECT_FALSE(cull_rect.Cutout(diff_rect).has_value()) << label;
2683 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), IRect()) << label;
2684 check_empty_flips(diff_rect, label);
2685 };
2686
2687 // Skim the corners and edge
2688 non_reducing(IRect::MakeLTRB(10, 10, 20, 20), "outside UL corner");
2689 non_reducing(IRect::MakeLTRB(20, 10, 40, 20), "Above");
2690 non_reducing(IRect::MakeLTRB(40, 10, 50, 20), "outside UR corner");
2691 non_reducing(IRect::MakeLTRB(40, 20, 50, 40), "Right");
2692 non_reducing(IRect::MakeLTRB(40, 40, 50, 50), "outside LR corner");
2693 non_reducing(IRect::MakeLTRB(20, 40, 40, 50), "Below");
2694 non_reducing(IRect::MakeLTRB(10, 40, 20, 50), "outside LR corner");
2695 non_reducing(IRect::MakeLTRB(10, 20, 20, 40), "Left");
2696
2697 // Overlap corners
2698 non_reducing(IRect::MakeLTRB(15, 15, 25, 25), "covering UL corner");
2699 non_reducing(IRect::MakeLTRB(35, 15, 45, 25), "covering UR corner");
2700 non_reducing(IRect::MakeLTRB(35, 35, 45, 45), "covering LR corner");
2701 non_reducing(IRect::MakeLTRB(15, 35, 25, 45), "covering LL corner");
2702
2703 // Overlap edges, but not across an entire side
2704 non_reducing(IRect::MakeLTRB(20, 15, 39, 25), "Top edge left-biased");
2705 non_reducing(IRect::MakeLTRB(21, 15, 40, 25), "Top edge, right biased");
2706 non_reducing(IRect::MakeLTRB(35, 20, 45, 39), "Right edge, top-biased");
2707 non_reducing(IRect::MakeLTRB(35, 21, 45, 40), "Right edge, bottom-biased");
2708 non_reducing(IRect::MakeLTRB(20, 35, 39, 45), "Bottom edge, left-biased");
2709 non_reducing(IRect::MakeLTRB(21, 35, 40, 45), "Bottom edge, right-biased");
2710 non_reducing(IRect::MakeLTRB(15, 20, 25, 39), "Left edge, top-biased");
2711 non_reducing(IRect::MakeLTRB(15, 21, 25, 40), "Left edge, bottom-biased");
2712
2713 // Slice all the way through the middle
2714 non_reducing(IRect::MakeLTRB(25, 15, 35, 45), "Vertical interior slice");
2715 non_reducing(IRect::MakeLTRB(15, 25, 45, 35), "Horizontal interior slice");
2716
2717 // Slice off each edge
2718 reducing(IRect::MakeLTRB(20, 15, 40, 25), //
2719 IRect::MakeLTRB(20, 25, 40, 40), //
2720 "Slice off top");
2721 reducing(IRect::MakeLTRB(35, 20, 45, 40), //
2722 IRect::MakeLTRB(20, 20, 35, 40), //
2723 "Slice off right");
2724 reducing(IRect::MakeLTRB(20, 35, 40, 45), //
2725 IRect::MakeLTRB(20, 20, 40, 35), //
2726 "Slice off bottom");
2727 reducing(IRect::MakeLTRB(15, 20, 25, 40), //
2728 IRect::MakeLTRB(25, 20, 40, 40), //
2729 "Slice off left");
2730
2731 // cull rect contains diff rect
2732 non_reducing(IRect::MakeLTRB(21, 21, 39, 39), "Contained, non-covering");
2733
2734 // cull rect equals diff rect
2735 emptying(cull_rect, "Perfectly covering");
2736
2737 // diff rect contains cull rect
2738 emptying(IRect::MakeLTRB(15, 15, 45, 45), "Smothering");
2739 }

References impeller::TRect< T >::Cutout(), impeller::TRect< T >::CutoutOrEmpty(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< int64_t >::MakeLTRB().

## ◆ TEST() [253/370]

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

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

Definition at line 794 of file rect_unittests.cc.

794 {
795 IRect rect = IRect::MakeLTRB(50, 50, 100, 100);
796
797 auto test = [&rect](int64_t l, int64_t t, int64_t r, int64_t b,
798 const std::string& label) {
799 EXPECT_FALSE(rect.IntersectsWithRect(IRect::MakeLTRB(l, b, r, t)))
800 << label << " with Top/Bottom swapped";
801 EXPECT_FALSE(rect.IntersectsWithRect(IRect::MakeLTRB(r, b, l, t)))
802 << label << " with Left/Right swapped";
803 EXPECT_FALSE(rect.IntersectsWithRect(IRect::MakeLTRB(r, t, l, b)))
804 << label << " with all sides swapped";
805 };
806
807 test(20, 20, 30, 30, "Above and Left");
808 test(70, 20, 80, 30, "Above");
809 test(120, 20, 130, 30, "Above and Right");
810 test(120, 70, 130, 80, "Right");
811 test(120, 120, 130, 130, "Below and Right");
812 test(70, 120, 80, 130, "Below");
813 test(20, 120, 30, 130, "Below and Left");
814 test(20, 70, 30, 80, "Left");
815
816 test(70, 70, 80, 80, "Inside");
817
818 test(40, 70, 60, 80, "Straddling Left");
819 test(70, 40, 80, 60, "Straddling Top");
820 test(90, 70, 110, 80, "Straddling Right");
821 test(70, 90, 80, 110, "Straddling Bottom");
822 }

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

## ◆ TEST() [255/370]

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

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

Definition at line 1238 of file rect_unittests.cc.

1238 {
1239 auto rect = IRect::MakeLTRB(100, 100, 200, 200);
1240
1241 // Expand(T amount)
1242 EXPECT_EQ(rect.Expand(10), IRect::MakeLTRB(90, 90, 210, 210));
1243 EXPECT_EQ(rect.Expand(-10), IRect::MakeLTRB(110, 110, 190, 190));
1244
1245 // Expand(amount, amount)
1246 EXPECT_EQ(rect.Expand(10, 10), IRect::MakeLTRB(90, 90, 210, 210));
1247 EXPECT_EQ(rect.Expand(10, -10), IRect::MakeLTRB(90, 110, 210, 190));
1248 EXPECT_EQ(rect.Expand(-10, 10), IRect::MakeLTRB(110, 90, 190, 210));
1249 EXPECT_EQ(rect.Expand(-10, -10), IRect::MakeLTRB(110, 110, 190, 190));
1250
1251 // Expand(amount, amount, amount, amount)
1252 EXPECT_EQ(rect.Expand(10, 20, 30, 40), IRect::MakeLTRB(90, 80, 230, 240));
1253 EXPECT_EQ(rect.Expand(-10, 20, 30, 40), IRect::MakeLTRB(110, 80, 230, 240));
1254 EXPECT_EQ(rect.Expand(10, -20, 30, 40), IRect::MakeLTRB(90, 120, 230, 240));
1255 EXPECT_EQ(rect.Expand(10, 20, -30, 40), IRect::MakeLTRB(90, 80, 170, 240));
1256 EXPECT_EQ(rect.Expand(10, 20, 30, -40), IRect::MakeLTRB(90, 80, 230, 160));
1257
1258 // Expand(IPoint amount)
1259 EXPECT_EQ(rect.Expand(IPoint{10, 10}), IRect::MakeLTRB(90, 90, 210, 210));
1260 EXPECT_EQ(rect.Expand(IPoint{10, -10}), IRect::MakeLTRB(90, 110, 210, 190));
1261 EXPECT_EQ(rect.Expand(IPoint{-10, 10}), IRect::MakeLTRB(110, 90, 190, 210));
1262 EXPECT_EQ(rect.Expand(IPoint{-10, -10}), IRect::MakeLTRB(110, 110, 190, 190));
1263
1264 // Expand(ISize amount)
1265 EXPECT_EQ(rect.Expand(ISize{10, 10}), IRect::MakeLTRB(90, 90, 210, 210));
1266 EXPECT_EQ(rect.Expand(ISize{10, -10}), IRect::MakeLTRB(90, 110, 210, 190));
1267 EXPECT_EQ(rect.Expand(ISize{-10, 10}), IRect::MakeLTRB(110, 90, 190, 210));
1268 EXPECT_EQ(rect.Expand(ISize{-10, -10}), IRect::MakeLTRB(110, 110, 190, 190));
1269 }

References impeller::TRect< int64_t >::MakeLTRB().

## ◆ TEST() [257/370]

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

Definition at line 616 of file rect_unittests.cc.

616 {
617 EXPECT_EQ(IRect(IRect::MakeXYWH(2, 3, 7, 15)), //
618 IRect::MakeXYWH(2, 3, 7, 15));
619 EXPECT_EQ(IRect(IRect::MakeLTRB(2, 3, 7, 15)), //
620 IRect::MakeLTRB(2, 3, 7, 15));
621 }

References impeller::TRect< int64_t >::MakeLTRB(), and impeller::TRect< int64_t >::MakeXYWH().

## ◆ TEST() [258/370]

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

Definition at line 1077 of file rect_unittests.cc.

1077 {
1078 {
1079 // Checks for expected matrix values
1080
1081 auto r = IRect::MakeXYWH(100, 200, 200, 400);
1082
1083 EXPECT_EQ(r.GetNormalizingTransform(),
1084 Matrix::MakeScale({0.005, 0.0025, 1.0}) *
1085 Matrix::MakeTranslation({-100, -200}));
1086 }
1087
1088 {
1089 // Checks for expected transform of points relative to the rect
1090
1091 auto r = IRect::MakeLTRB(300, 500, 400, 700);
1092 auto m = r.GetNormalizingTransform();
1093
1094 // The 4 corners of the rect => (0, 0) to (1, 1)
1095 EXPECT_EQ(m * Point(300, 500), Point(0, 0));
1096 EXPECT_EQ(m * Point(400, 500), Point(1, 0));
1097 EXPECT_EQ(m * Point(400, 700), Point(1, 1));
1098 EXPECT_EQ(m * Point(300, 700), Point(0, 1));
1099
1100 // The center => (0.5, 0.5)
1101 EXPECT_EQ(m * Point(350, 600), Point(0.5, 0.5));
1102
1103 // Outside the 4 corners => (-1, -1) to (2, 2)
1104 EXPECT_EQ(m * Point(200, 300), Point(-1, -1));
1105 EXPECT_EQ(m * Point(500, 300), Point(2, -1));
1106 EXPECT_EQ(m * Point(500, 900), Point(2, 2));
1107 EXPECT_EQ(m * Point(200, 900), Point(-1, 2));
1108 }
1109
1110 {
1111 // Checks for behavior with empty rects
1112
1113 auto zero = Matrix::MakeScale({0.0, 0.0, 1.0});
1114
1115 // Empty for width and/or height == 0
1116 EXPECT_EQ(IRect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
1117 EXPECT_EQ(IRect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
1118 EXPECT_EQ(IRect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
1119
1120 // Empty for width and/or height < 0
1121 EXPECT_EQ(IRect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
1122 EXPECT_EQ(IRect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
1123 EXPECT_EQ(IRect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
1124 }
1125 }

References impeller::TRect< int64_t >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::TRect< int64_t >::MakeXYWH().

## ◆ TEST() [259/370]

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

Definition at line 1751 of file rect_unittests.cc.

1751 {
1752 auto check_empty_flips = [](const IRect& a, const IRect& b,
1753 const std::string& label) {
1754 ASSERT_FALSE(a.IsEmpty());
1755 // b is allowed to be empty
1756
1757 // unflipped a vs flipped (empty) b yields a
1758 EXPECT_FALSE(a.Intersection(flip_lr(b)).has_value()) << label;
1759 EXPECT_FALSE(a.Intersection(flip_tb(b)).has_value()) << label;
1760 EXPECT_FALSE(a.Intersection(flip_lrtb(b)).has_value()) << label;
1761
1762 // flipped (empty) a vs unflipped b yields b
1763 EXPECT_FALSE(flip_lr(a).Intersection(b).has_value()) << label;
1764 EXPECT_FALSE(flip_tb(a).Intersection(b).has_value()) << label;
1765 EXPECT_FALSE(flip_lrtb(a).Intersection(b).has_value()) << label;
1766
1767 // flipped (empty) a vs flipped (empty) b yields empty
1768 EXPECT_FALSE(flip_lr(a).Intersection(flip_lr(b)).has_value()) << label;
1769 EXPECT_FALSE(flip_tb(a).Intersection(flip_tb(b)).has_value()) << label;
1770 EXPECT_FALSE(flip_lrtb(a).Intersection(flip_lrtb(b)).has_value()) << label;
1771 };
1772
1773 auto test_non_empty = [&check_empty_flips](const IRect& a, const IRect& b,
1774 const IRect& result) {
1775 ASSERT_FALSE(a.IsEmpty()) << a;
1776 // b is allowed to be empty
1777
1778 std::stringstream stream;
1779 stream << a << " union " << b;
1780 auto label = stream.str();
1781
1782 EXPECT_TRUE(a.Intersection(b).has_value()) << label;
1783 EXPECT_TRUE(b.Intersection(a).has_value()) << label;
1784 EXPECT_EQ(a.Intersection(b), result) << label;
1785 EXPECT_EQ(b.Intersection(a), result) << label;
1786 check_empty_flips(a, b, label);
1787 };
1788
1789 auto test_empty = [&check_empty_flips](const IRect& a, const IRect& b) {
1790 ASSERT_FALSE(a.IsEmpty()) << a;
1791 // b is allowed to be empty
1792
1793 std::stringstream stream;
1794 stream << a << " union " << b;
1795 auto label = stream.str();
1796
1797 EXPECT_FALSE(a.Intersection(b).has_value()) << label;
1798 EXPECT_FALSE(b.Intersection(a).has_value()) << label;
1799 check_empty_flips(a, b, label);
1800 };
1801
1802 {
1803 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1804 auto b = IRect::MakeXYWH(0, 0, 0, 0);
1805
1806 test_empty(a, b);
1807 }
1808
1809 {
1810 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1811 auto b = IRect::MakeXYWH(10, 10, 0, 0);
1812
1813 test_empty(a, b);
1814 }
1815
1816 {
1817 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1818 auto b = IRect::MakeXYWH(10, 10, 100, 100);
1819 auto expected = IRect::MakeXYWH(10, 10, 90, 90);
1820
1821 test_non_empty(a, b, expected);
1822 }
1823
1824 {
1825 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1826 auto b = IRect::MakeXYWH(100, 100, 100, 100);
1827
1828 test_empty(a, b);
1829 }
1830
1831 {
1832 auto a = IRect::MakeMaximum();
1833 auto b = IRect::MakeXYWH(10, 10, 300, 300);
1834
1835 test_non_empty(a, b, b);
1836 }
1837
1838 {
1839 auto a = IRect::MakeMaximum();
1840 auto b = IRect::MakeMaximum();
1841
1842 test_non_empty(a, b, IRect::MakeMaximum());
1843 }
1844 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::Intersection(), impeller::TRect< T >::IsEmpty(), impeller::TRect< int64_t >::MakeMaximum(), and impeller::TRect< int64_t >::MakeXYWH().

## ◆ TEST() [260/370]

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

Definition at line 2016 of file rect_unittests.cc.

2016 {
2017 auto check_empty_flips = [](const IRect& a, const IRect& b,
2018 const std::string& label) {
2019 ASSERT_FALSE(a.IsEmpty());
2020 // b is allowed to be empty
2021
2022 // unflipped a vs flipped (empty) b yields a
2023 EXPECT_FALSE(a.IntersectsWithRect(flip_lr(b))) << label;
2024 EXPECT_FALSE(a.IntersectsWithRect(flip_tb(b))) << label;
2025 EXPECT_FALSE(a.IntersectsWithRect(flip_lrtb(b))) << label;
2026
2027 // flipped (empty) a vs unflipped b yields b
2028 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(b)) << label;
2029 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(b)) << label;
2030 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(b)) << label;
2031
2032 // flipped (empty) a vs flipped (empty) b yields empty
2033 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(flip_lr(b))) << label;
2034 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(flip_tb(b))) << label;
2035 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(flip_lrtb(b))) << label;
2036 };
2037
2038 auto test_non_empty = [&check_empty_flips](const IRect& a, const IRect& b) {
2039 ASSERT_FALSE(a.IsEmpty()) << a;
2040 // b is allowed to be empty
2041
2042 std::stringstream stream;
2043 stream << a << " union " << b;
2044 auto label = stream.str();
2045
2046 EXPECT_TRUE(a.IntersectsWithRect(b)) << label;
2047 EXPECT_TRUE(b.IntersectsWithRect(a)) << label;
2048 check_empty_flips(a, b, label);
2049 };
2050
2051 auto test_empty = [&check_empty_flips](const IRect& a, const IRect& b) {
2052 ASSERT_FALSE(a.IsEmpty()) << a;
2053 // b is allowed to be empty
2054
2055 std::stringstream stream;
2056 stream << a << " union " << b;
2057 auto label = stream.str();
2058
2059 EXPECT_FALSE(a.IntersectsWithRect(b)) << label;
2060 EXPECT_FALSE(b.IntersectsWithRect(a)) << label;
2061 check_empty_flips(a, b, label);
2062 };
2063
2064 {
2065 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2066 auto b = IRect::MakeXYWH(0, 0, 0, 0);
2067
2068 test_empty(a, b);
2069 }
2070
2071 {
2072 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2073 auto b = IRect::MakeXYWH(10, 10, 0, 0);
2074
2075 test_empty(a, b);
2076 }
2077
2078 {
2079 auto a = IRect::MakeXYWH(0, 0, 100, 100);
2080 auto b = IRect::MakeXYWH(10, 10, 100, 100);
2081
2082 test_non_empty(a, b);
2083 }
2084
2085 {
2086 auto a = IRect::MakeXYWH(0, 0, 100, 100);
2087 auto b = IRect::MakeXYWH(100, 100, 100, 100);
2088
2089 test_empty(a, b);
2090 }
2091
2092 {
2093 auto a = IRect::MakeMaximum();
2094 auto b = IRect::MakeXYWH(10, 10, 100, 100);
2095
2096 test_non_empty(a, b);
2097 }
2098
2099 {
2100 auto a = IRect::MakeMaximum();
2101 auto b = IRect::MakeMaximum();
2102
2103 test_non_empty(a, b);
2104 }
2105 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IntersectsWithRect(), impeller::TRect< T >::IsEmpty(), impeller::TRect< int64_t >::MakeMaximum(), and impeller::TRect< int64_t >::MakeXYWH().

## ◆ TEST() [261/370]

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

Definition at line 593 of file rect_unittests.cc.

593 {
594 IRect rect = IRect::MakeMaximum();
595 auto min = std::numeric_limits<int64_t>::min();
596 auto max = std::numeric_limits<int64_t>::max();
597
598 EXPECT_EQ(rect.GetLeft(), min);
599 EXPECT_EQ(rect.GetTop(), min);
600 EXPECT_EQ(rect.GetRight(), max);
601 EXPECT_EQ(rect.GetBottom(), max);
602 EXPECT_EQ(rect.GetX(), min);
603 EXPECT_EQ(rect.GetY(), min);
604 EXPECT_EQ(rect.GetWidth(), max);
605 EXPECT_EQ(rect.GetHeight(), max);
606 EXPECT_FALSE(rect.IsEmpty());
607 }

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< int64_t >::MakeMaximum().

## ◆ TEST() [262/370]

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

Definition at line 683 of file rect_unittests.cc.

683 {
684 {
685 IRect r = IRect::MakeOriginSize({10, 20}, {50, 40});
686 EXPECT_EQ(r.GetOrigin(), IPoint(10, 20));
687 EXPECT_EQ(r.GetSize(), ISize(50, 40));
688 EXPECT_EQ(r.GetX(), 10);
689 EXPECT_EQ(r.GetY(), 20);
690 EXPECT_EQ(r.GetWidth(), 50);
691 EXPECT_EQ(r.GetHeight(), 40);
692 auto expected_array = std::array<int64_t, 4>{10, 20, 50, 40};
693 EXPECT_EQ(r.GetXYWH(), expected_array);
694 }
695
696 {
697 IRect r = IRect::MakeLTRB(10, 20, 50, 40);
698 EXPECT_EQ(r.GetOrigin(), IPoint(10, 20));
699 EXPECT_EQ(r.GetSize(), ISize(40, 20));
700 EXPECT_EQ(r.GetX(), 10);
701 EXPECT_EQ(r.GetY(), 20);
702 EXPECT_EQ(r.GetWidth(), 40);
703 EXPECT_EQ(r.GetHeight(), 20);
704 auto expected_array = std::array<int64_t, 4>{10, 20, 40, 20};
705 EXPECT_EQ(r.GetXYWH(), expected_array);
706 }
707 }

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< int64_t >::MakeLTRB(), and impeller::TRect< int64_t >::MakeOriginSize().

## ◆ TEST() [263/370]

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

Definition at line 478 of file rect_unittests.cc.

478 {
479 auto min = std::numeric_limits<int64_t>::min();
480 auto max = std::numeric_limits<int64_t>::max();
481
482 // 4 cases
483 // negative l, r near max takes width past max
484 // positive l, r near min takes width below min
485 // negative t, b near max takes width past max
486 // positive t, b near min takes width below min
487
488 {
489 IRect rect = IRect::MakeLTRB(-10, 10, max - 5, 26);
490
491 EXPECT_EQ(rect.GetLeft(), -10);
492 EXPECT_EQ(rect.GetTop(), 10);
493 EXPECT_EQ(rect.GetRight(), max - 5);
494 EXPECT_EQ(rect.GetBottom(), 26);
495 EXPECT_EQ(rect.GetX(), -10);
496 EXPECT_EQ(rect.GetY(), 10);
497 EXPECT_EQ(rect.GetWidth(), max);
498 EXPECT_EQ(rect.GetHeight(), 16);
499 EXPECT_FALSE(rect.IsEmpty());
500 }
501
502 {
503 IRect rect = IRect::MakeLTRB(10, 10, min + 5, 26);
504
505 EXPECT_EQ(rect.GetLeft(), 10);
506 EXPECT_EQ(rect.GetTop(), 10);
507 EXPECT_EQ(rect.GetRight(), min + 5);
508 EXPECT_EQ(rect.GetBottom(), 26);
509 EXPECT_EQ(rect.GetX(), 10);
510 EXPECT_EQ(rect.GetY(), 10);
511 EXPECT_EQ(rect.GetWidth(), min);
512 EXPECT_EQ(rect.GetHeight(), 16);
513 EXPECT_TRUE(rect.IsEmpty());
514 }
515
516 {
517 IRect rect = IRect::MakeLTRB(5, -10, 15, max - 5);
518
519 EXPECT_EQ(rect.GetLeft(), 5);
520 EXPECT_EQ(rect.GetTop(), -10);
521 EXPECT_EQ(rect.GetRight(), 15);
522 EXPECT_EQ(rect.GetBottom(), max - 5);
523 EXPECT_EQ(rect.GetX(), 5);
524 EXPECT_EQ(rect.GetY(), -10);
525 EXPECT_EQ(rect.GetWidth(), 10);
526 EXPECT_EQ(rect.GetHeight(), max);
527 EXPECT_FALSE(rect.IsEmpty());
528 }
529
530 {
531 IRect rect = IRect::MakeLTRB(5, 10, 15, min + 5);
532
533 EXPECT_EQ(rect.GetLeft(), 5);
534 EXPECT_EQ(rect.GetTop(), 10);
535 EXPECT_EQ(rect.GetRight(), 15);
536 EXPECT_EQ(rect.GetBottom(), min + 5);
537 EXPECT_EQ(rect.GetX(), 5);
538 EXPECT_EQ(rect.GetY(), 10);
539 EXPECT_EQ(rect.GetWidth(), 10);
540 EXPECT_EQ(rect.GetHeight(), min);
541 EXPECT_TRUE(rect.IsEmpty());
542 }
543 }

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< int64_t >::MakeLTRB().

## ◆ TEST() [264/370]

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

Definition at line 272 of file rect_unittests.cc.

272 {
273 auto min = std::numeric_limits<int64_t>::min();
274 auto max = std::numeric_limits<int64_t>::max();
275
276 // 4 cases
277 // x near max, positive w takes it past max
278 // x near min, negative w takes it below min
279 // y near max, positive h takes it past max
280 // y near min, negative h takes it below min
281
282 {
283 IRect rect = IRect::MakeXYWH(max - 5, 10, 10, 16);
284
285 EXPECT_EQ(rect.GetLeft(), max - 5);
286 EXPECT_EQ(rect.GetTop(), 10);
287 EXPECT_EQ(rect.GetRight(), max);
288 EXPECT_EQ(rect.GetBottom(), 26);
289 EXPECT_EQ(rect.GetX(), max - 5);
290 EXPECT_EQ(rect.GetY(), 10);
291 EXPECT_EQ(rect.GetWidth(), 5);
292 EXPECT_EQ(rect.GetHeight(), 16);
293 EXPECT_FALSE(rect.IsEmpty());
294 }
295
296 {
297 IRect rect = IRect::MakeXYWH(min + 5, 10, -10, 16);
298
299 EXPECT_EQ(rect.GetLeft(), min + 5);
300 EXPECT_EQ(rect.GetTop(), 10);
301 EXPECT_EQ(rect.GetRight(), min);
302 EXPECT_EQ(rect.GetBottom(), 26);
303 EXPECT_EQ(rect.GetX(), min + 5);
304 EXPECT_EQ(rect.GetY(), 10);
305 EXPECT_EQ(rect.GetWidth(), -5);
306 EXPECT_EQ(rect.GetHeight(), 16);
307 EXPECT_TRUE(rect.IsEmpty());
308 }
309
310 {
311 IRect rect = IRect::MakeXYWH(5, max - 10, 10, 16);
312
313 EXPECT_EQ(rect.GetLeft(), 5);
314 EXPECT_EQ(rect.GetTop(), max - 10);
315 EXPECT_EQ(rect.GetRight(), 15);
316 EXPECT_EQ(rect.GetBottom(), max);
317 EXPECT_EQ(rect.GetX(), 5);
318 EXPECT_EQ(rect.GetY(), max - 10);
319 EXPECT_EQ(rect.GetWidth(), 10);
320 EXPECT_EQ(rect.GetHeight(), 10);
321 EXPECT_FALSE(rect.IsEmpty());
322 }
323
324 {
325 IRect rect = IRect::MakeXYWH(5, min + 10, 10, -16);
326
327 EXPECT_EQ(rect.GetLeft(), 5);
328 EXPECT_EQ(rect.GetTop(), min + 10);
329 EXPECT_EQ(rect.GetRight(), 15);
330 EXPECT_EQ(rect.GetBottom(), min);
331 EXPECT_EQ(rect.GetX(), 5);
332 EXPECT_EQ(rect.GetY(), min + 10);
333 EXPECT_EQ(rect.GetWidth(), 10);
334 EXPECT_EQ(rect.GetHeight(), -10);
335 EXPECT_TRUE(rect.IsEmpty());
336 }
337 }

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< int64_t >::MakeXYWH().

## ◆ TEST() [265/370]

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

Definition at line 2852 of file rect_unittests.cc.

2852 {
2853 {
2854 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
2855 auto ir = IRect::MakeLTRB(-100, -100, 100, 100);
2856 EXPECT_EQ(IRect::RoundOut(r), ir);
2857 }
2858 {
2859 auto r = Rect::MakeLTRB(-100.1, -100.1, 100.1, 100.1);
2860 auto ir = IRect::MakeLTRB(-101, -101, 101, 101);
2861 EXPECT_EQ(IRect::RoundOut(r), ir);
2862 }
2863 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< int64_t >::MakeLTRB(), and impeller::TRect< int64_t >::RoundOut().

## ◆ TEST() [266/370]

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

Definition at line 929 of file rect_unittests.cc.

929 {
930 auto test1 = [](IRect rect, int64_t scale) {
931 IRect expected = IRect::MakeXYWH(rect.GetX() * scale, //
932 rect.GetY() * scale, //
933 rect.GetWidth() * scale, //
934 rect.GetHeight() * scale);
935
936 EXPECT_EQ(rect.Scale(scale), expected) //
937 << rect << " * " << scale;
938 EXPECT_EQ(rect.Scale(scale, scale), expected) //
939 << rect << " * " << scale;
940 EXPECT_EQ(rect.Scale(IPoint(scale, scale)), expected) //
941 << rect << " * " << scale;
942 EXPECT_EQ(rect.Scale(ISize(scale, scale)), expected) //
943 << rect << " * " << scale;
944 };
945
946 auto test2 = [&test1](IRect rect, int64_t scale_x, int64_t scale_y) {
947 IRect expected = IRect::MakeXYWH(rect.GetX() * scale_x, //
948 rect.GetY() * scale_y, //
949 rect.GetWidth() * scale_x, //
950 rect.GetHeight() * scale_y);
951
952 EXPECT_EQ(rect.Scale(scale_x, scale_y), expected) //
953 << rect << " * " << scale_x << ", " << scale_y;
954 EXPECT_EQ(rect.Scale(IPoint(scale_x, scale_y)), expected) //
955 << rect << " * " << scale_x << ", " << scale_y;
956 EXPECT_EQ(rect.Scale(ISize(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(IRect::MakeLTRB(10, 15, 100, 150), 2, 3);
964 test2(IRect::MakeLTRB(10, 15, 100, 150), 3, 2);
965 test2(IRect::MakeLTRB(10, 15, -100, 150), 2, 3);
966 test2(IRect::MakeLTRB(10, 15, 100, -150), 2, 3);
967 test2(IRect::MakeLTRB(10, 15, 100, 150), -2, 3);
968 test2(IRect::MakeLTRB(10, 15, 100, 150), 2, -3);
969 }

References impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< int64_t >::MakeLTRB(), impeller::TRect< int64_t >::MakeXYWH(), impeller::TRect< T >::Scale(), and scale.

## ◆ TEST() [267/370]

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< int64_t >::MakeLTRB().

## ◆ TEST() [268/370]

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< int64_t >::MakeXYWH().

## ◆ TEST() [269/370]

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

Definition at line 1456 of file rect_unittests.cc.

1456 {
1457 auto check_empty_flips = [](const IRect& a, const IRect& b,
1458 const std::string& label) {
1459 ASSERT_FALSE(a.IsEmpty());
1460 // b is allowed to be empty
1461
1462 // unflipped a vs flipped (empty) b yields a
1463 EXPECT_EQ(a.Union(flip_lr(b)), a) << label;
1464 EXPECT_EQ(a.Union(flip_tb(b)), a) << label;
1465 EXPECT_EQ(a.Union(flip_lrtb(b)), a) << label;
1466
1467 // flipped (empty) a vs unflipped b yields b
1468 EXPECT_EQ(flip_lr(a).Union(b), b) << label;
1469 EXPECT_EQ(flip_tb(a).Union(b), b) << label;
1470 EXPECT_EQ(flip_lrtb(a).Union(b), b) << label;
1471
1472 // flipped (empty) a vs flipped (empty) b yields empty
1473 EXPECT_TRUE(flip_lr(a).Union(flip_lr(b)).IsEmpty()) << label;
1474 EXPECT_TRUE(flip_tb(a).Union(flip_tb(b)).IsEmpty()) << label;
1475 EXPECT_TRUE(flip_lrtb(a).Union(flip_lrtb(b)).IsEmpty()) << label;
1476 };
1477
1478 auto test = [&check_empty_flips](const IRect& a, const IRect& b,
1479 const IRect& result) {
1480 ASSERT_FALSE(a.IsEmpty()) << a;
1481 // b is allowed to be empty
1482
1483 std::stringstream stream;
1484 stream << a << " union " << b;
1485 auto label = stream.str();
1486
1487 EXPECT_EQ(a.Union(b), result) << label;
1488 EXPECT_EQ(b.Union(a), result) << label;
1489 check_empty_flips(a, b, label);
1490 };
1491
1492 {
1493 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1494 auto b = IRect::MakeXYWH(0, 0, 0, 0);
1495 auto expected = IRect::MakeXYWH(100, 100, 100, 100);
1496 test(a, b, expected);
1497 }
1498
1499 {
1500 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1501 auto b = IRect::MakeXYWH(0, 0, 1, 1);
1502 auto expected = IRect::MakeXYWH(0, 0, 200, 200);
1503 test(a, b, expected);
1504 }
1505
1506 {
1507 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1508 auto b = IRect::MakeXYWH(10, 10, 1, 1);
1509 auto expected = IRect::MakeXYWH(10, 10, 190, 190);
1510 test(a, b, expected);
1511 }
1512
1513 {
1514 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1515 auto b = IRect::MakeXYWH(10, 10, 100, 100);
1516 auto expected = IRect::MakeXYWH(0, 0, 110, 110);
1517 test(a, b, expected);
1518 }
1519
1520 {
1521 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1522 auto b = IRect::MakeXYWH(100, 100, 100, 100);
1523 auto expected = IRect::MakeXYWH(0, 0, 200, 200);
1524 test(a, b, expected);
1525 }
1526 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< int64_t >::MakeXYWH(), and impeller::TRect< T >::Union().

## ◆ TEST() [270/370]

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

Definition at line 1151 of file rect_unittests.cc.

1151 {
1152 // Non-empty
1153 EXPECT_FALSE(IRect::MakeXYWH(1, 2, 10, 7).IsEmpty());
1154
1155 // Empty both width and height both 0 or negative, in all combinations
1156 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 0).IsEmpty());
1157 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, -1).IsEmpty());
1158 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 0).IsEmpty());
1159 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, -1).IsEmpty());
1160
1161 // Empty for 0 or negative width or height (but not both at the same time)
1162 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, 0).IsEmpty());
1163 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, -1).IsEmpty());
1164 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 7).IsEmpty());
1165 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 7).IsEmpty());
1166 }

References impeller::TRect< int64_t >::MakeXYWH().

## ◆ TEST() [271/370]

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

Definition at line 1182 of file rect_unittests.cc.

1182 {
1183 EXPECT_TRUE(Rect::MakeXYWH(10, 30, 20, 20).IsSquare());
1184 EXPECT_FALSE(Rect::MakeXYWH(10, 30, 20, 19).IsSquare());
1185 EXPECT_FALSE(Rect::MakeXYWH(10, 30, 19, 20).IsSquare());
1186 EXPECT_TRUE(Rect::MakeMaximum().IsSquare());
1187
1188 EXPECT_TRUE(IRect::MakeXYWH(10, 30, 20, 20).IsSquare());
1189 EXPECT_FALSE(IRect::MakeXYWH(10, 30, 20, 19).IsSquare());
1190 EXPECT_FALSE(IRect::MakeXYWH(10, 30, 19, 20).IsSquare());
1191 EXPECT_TRUE(IRect::MakeMaximum().IsSquare());
1192 }

References impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< int64_t >::MakeMaximum(), impeller::TRect< int64_t >::MakeXYWH(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [272/370]

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

Definition at line 1168 of file rect_unittests.cc.

1168 {
1169 Quad quad = {
1170 Point(10, 10),
1171 Point(20, 10),
1172 Point(10, 20),
1173 Point(20, 20),
1174 };
1175 std::optional<Rect> bounds = Rect::MakePointBounds(quad);
1176 EXPECT_TRUE(bounds.has_value());
1177 if (bounds.has_value()) {
1178 EXPECT_TRUE(RectNear(bounds.value(), Rect::MakeLTRB(10, 10, 20, 20)));
1179 }
1180 }

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

## ◆ TEST() [273/370]

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

Definition at line 1846 of file rect_unittests.cc.

1846 {
1847 auto a = IRect::MakeLTRB(0, 0, 110, 110);
1848 auto b = IRect::MakeLTRB(100, 100, 200, 200);
1849 auto c = IRect::MakeLTRB(100, 0, 200, 110);
1850
1851 // NullOpt, NullOpt
1852 EXPECT_FALSE(IRect::Intersection(std::nullopt, std::nullopt).has_value());
1853 EXPECT_EQ(IRect::Intersection(std::nullopt, std::nullopt), std::nullopt);
1854
1855 auto test1 = [](const IRect& r) {
1856 // Rect, NullOpt
1857 EXPECT_TRUE(IRect::Intersection(r, std::nullopt).has_value());
1858 EXPECT_EQ(IRect::Intersection(r, std::nullopt).value(), r);
1859
1860 // OptRect, NullOpt
1861 EXPECT_TRUE(
1862 IRect::Intersection(std::optional(r), std::nullopt).has_value());
1863 EXPECT_EQ(IRect::Intersection(std::optional(r), std::nullopt).value(), r);
1864
1865 // NullOpt, Rect
1866 EXPECT_TRUE(IRect::Intersection(std::nullopt, r).has_value());
1867 EXPECT_EQ(IRect::Intersection(std::nullopt, r).value(), r);
1868
1869 // NullOpt, OptRect
1870 EXPECT_TRUE(
1871 IRect::Intersection(std::nullopt, std::optional(r)).has_value());
1872 EXPECT_EQ(IRect::Intersection(std::nullopt, std::optional(r)).value(), r);
1873 };
1874
1875 test1(a);
1876 test1(b);
1877 test1(c);
1878
1879 auto test2 = [](const IRect& a, const IRect& b, const IRect& i) {
1880 ASSERT_EQ(a.Intersection(b), i);
1881
1882 // Rect, OptRect
1883 EXPECT_TRUE(IRect::Intersection(a, std::optional(b)).has_value());
1884 EXPECT_EQ(IRect::Intersection(a, std::optional(b)).value(), i);
1885
1886 // OptRect, Rect
1887 EXPECT_TRUE(IRect::Intersection(std::optional(a), b).has_value());
1888 EXPECT_EQ(IRect::Intersection(std::optional(a), b).value(), i);
1889
1890 // OptRect, OptRect
1891 EXPECT_TRUE(
1892 IRect::Intersection(std::optional(a), std::optional(b)).has_value());
1893 EXPECT_EQ(IRect::Intersection(std::optional(a), std::optional(b)).value(),
1894 i);
1895 };
1896
1897 test2(a, b, IRect::MakeLTRB(100, 100, 110, 110));
1898 test2(a, c, IRect::MakeLTRB(100, 0, 110, 110));
1899 test2(b, c, IRect::MakeLTRB(100, 100, 200, 110));
1900 }

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

## ◆ TEST() [274/370]

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

Definition at line 1528 of file rect_unittests.cc.

1528 {
1529 auto a = IRect::MakeLTRB(0, 0, 100, 100);
1530 auto b = IRect::MakeLTRB(100, 100, 200, 200);
1531 auto c = IRect::MakeLTRB(100, 0, 200, 100);
1532
1533 // NullOpt, NullOpt
1534 EXPECT_FALSE(IRect::Union(std::nullopt, std::nullopt).has_value());
1535 EXPECT_EQ(IRect::Union(std::nullopt, std::nullopt), std::nullopt);
1536
1537 auto test1 = [](const IRect& r) {
1538 // Rect, NullOpt
1539 EXPECT_TRUE(IRect::Union(r, std::nullopt).has_value());
1540 EXPECT_EQ(IRect::Union(r, std::nullopt).value(), r);
1541
1542 // OptRect, NullOpt
1543 EXPECT_TRUE(IRect::Union(std::optional(r), std::nullopt).has_value());
1544 EXPECT_EQ(IRect::Union(std::optional(r), std::nullopt).value(), r);
1545
1546 // NullOpt, Rect
1547 EXPECT_TRUE(IRect::Union(std::nullopt, r).has_value());
1548 EXPECT_EQ(IRect::Union(std::nullopt, r).value(), r);
1549
1550 // NullOpt, OptRect
1551 EXPECT_TRUE(IRect::Union(std::nullopt, std::optional(r)).has_value());
1552 EXPECT_EQ(IRect::Union(std::nullopt, std::optional(r)).value(), r);
1553 };
1554
1555 test1(a);
1556 test1(b);
1557 test1(c);
1558
1559 auto test2 = [](const IRect& a, const IRect& b, const IRect& u) {
1560 ASSERT_EQ(a.Union(b), u);
1561
1562 // Rect, OptRect
1563 EXPECT_TRUE(IRect::Union(a, std::optional(b)).has_value());
1564 EXPECT_EQ(IRect::Union(a, std::optional(b)).value(), u);
1565
1566 // OptRect, Rect
1567 EXPECT_TRUE(IRect::Union(std::optional(a), b).has_value());
1568 EXPECT_EQ(IRect::Union(std::optional(a), b).value(), u);
1569
1570 // OptRect, OptRect
1571 EXPECT_TRUE(IRect::Union(std::optional(a), std::optional(b)).has_value());
1572 EXPECT_EQ(IRect::Union(std::optional(a), std::optional(b)).value(), u);
1573 };
1574
1575 test2(a, b, IRect::MakeLTRB(0, 0, 200, 200));
1576 test2(a, c, IRect::MakeLTRB(0, 0, 200, 100));
1577 test2(b, c, IRect::MakeLTRB(100, 0, 200, 200));
1578 }

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

## ◆ TEST() [275/370]

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

Definition at line 1697 of file rect_unittests.cc.

1697 {
1698 auto a = Rect::MakeLTRB(0, 0, 110, 110);
1699 auto b = Rect::MakeLTRB(100, 100, 200, 200);
1700 auto c = Rect::MakeLTRB(100, 0, 200, 110);
1701
1702 // NullOpt, NullOpt
1703 EXPECT_FALSE(Rect::Intersection(std::nullopt, std::nullopt).has_value());
1704 EXPECT_EQ(Rect::Intersection(std::nullopt, std::nullopt), std::nullopt);
1705
1706 auto test1 = [](const Rect& r) {
1707 // Rect, NullOpt
1708 EXPECT_TRUE(Rect::Intersection(r, std::nullopt).has_value());
1709 EXPECT_EQ(Rect::Intersection(r, std::nullopt).value(), r);
1710
1711 // OptRect, NullOpt
1712 EXPECT_TRUE(Rect::Intersection(std::optional(r), std::nullopt).has_value());
1713 EXPECT_EQ(Rect::Intersection(std::optional(r), std::nullopt).value(), r);
1714
1715 // NullOpt, Rect
1716 EXPECT_TRUE(Rect::Intersection(std::nullopt, r).has_value());
1717 EXPECT_EQ(Rect::Intersection(std::nullopt, r).value(), r);
1718
1719 // NullOpt, OptRect
1720 EXPECT_TRUE(Rect::Intersection(std::nullopt, std::optional(r)).has_value());
1721 EXPECT_EQ(Rect::Intersection(std::nullopt, std::optional(r)).value(), r);
1722 };
1723
1724 test1(a);
1725 test1(b);
1726 test1(c);
1727
1728 auto test2 = [](const Rect& a, const Rect& b, const Rect& i) {
1729 ASSERT_EQ(a.Intersection(b), i);
1730
1731 // Rect, OptRect
1732 EXPECT_TRUE(Rect::Intersection(a, std::optional(b)).has_value());
1733 EXPECT_EQ(Rect::Intersection(a, std::optional(b)).value(), i);
1734
1735 // OptRect, Rect
1736 EXPECT_TRUE(Rect::Intersection(std::optional(a), b).has_value());
1737 EXPECT_EQ(Rect::Intersection(std::optional(a), b).value(), i);
1738
1739 // OptRect, OptRect
1740 EXPECT_TRUE(
1741 Rect::Intersection(std::optional(a), std::optional(b)).has_value());
1742 EXPECT_EQ(Rect::Intersection(std::optional(a), std::optional(b)).value(),
1743 i);
1744 };
1745
1746 test2(a, b, Rect::MakeLTRB(100, 100, 110, 110));
1747 test2(a, c, Rect::MakeLTRB(100, 0, 110, 110));
1748 test2(b, c, Rect::MakeLTRB(100, 100, 200, 110));
1749 }

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

## ◆ TEST() [276/370]

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

Definition at line 1404 of file rect_unittests.cc.

1404 {
1405 auto a = Rect::MakeLTRB(0, 0, 100, 100);
1406 auto b = Rect::MakeLTRB(100, 100, 200, 200);
1407 auto c = Rect::MakeLTRB(100, 0, 200, 100);
1408
1409 // NullOpt, NullOpt
1410 EXPECT_FALSE(Rect::Union(std::nullopt, std::nullopt).has_value());
1411 EXPECT_EQ(Rect::Union(std::nullopt, std::nullopt), std::nullopt);
1412
1413 auto test1 = [](const Rect& r) {
1414 // Rect, NullOpt
1415 EXPECT_TRUE(Rect::Union(r, std::nullopt).has_value());
1416 EXPECT_EQ(Rect::Union(r, std::nullopt).value(), r);
1417
1418 // OptRect, NullOpt
1419 EXPECT_TRUE(Rect::Union(std::optional(r), std::nullopt).has_value());
1420 EXPECT_EQ(Rect::Union(std::optional(r), std::nullopt).value(), r);
1421
1422 // NullOpt, Rect
1423 EXPECT_TRUE(Rect::Union(std::nullopt, r).has_value());
1424 EXPECT_EQ(Rect::Union(std::nullopt, r).value(), r);
1425
1426 // NullOpt, OptRect
1427 EXPECT_TRUE(Rect::Union(std::nullopt, std::optional(r)).has_value());
1428 EXPECT_EQ(Rect::Union(std::nullopt, std::optional(r)).value(), r);
1429 };
1430
1431 test1(a);
1432 test1(b);
1433 test1(c);
1434
1435 auto test2 = [](const Rect& a, const Rect& b, const Rect& u) {
1436 ASSERT_EQ(a.Union(b), u);
1437
1438 // Rect, OptRect
1439 EXPECT_TRUE(Rect::Union(a, std::optional(b)).has_value());
1440 EXPECT_EQ(Rect::Union(a, std::optional(b)).value(), u);
1441
1442 // OptRect, Rect
1443 EXPECT_TRUE(Rect::Union(std::optional(a), b).has_value());
1444 EXPECT_EQ(Rect::Union(std::optional(a), b).value(), u);
1445
1446 // OptRect, OptRect
1447 EXPECT_TRUE(Rect::Union(std::optional(a), std::optional(b)).has_value());
1448 EXPECT_EQ(Rect::Union(std::optional(a), std::optional(b)).value(), u);
1449 };
1450
1451 test2(a, b, Rect::MakeLTRB(0, 0, 200, 200));
1452 test2(a, c, Rect::MakeLTRB(0, 0, 200, 100));
1453 test2(b, c, Rect::MakeLTRB(100, 0, 200, 200));
1454 }

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

## ◆ TEST() [277/370]

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

Definition at line 971 of file rect_unittests.cc.

971 {
972 EXPECT_EQ(Rect::MakeXYWH(0, 0, 100, 200).Area(), 20000);
973 EXPECT_EQ(Rect::MakeXYWH(10, 20, 100, 200).Area(), 20000);
974 EXPECT_EQ(Rect::MakeXYWH(0, 0, 200, 100).Area(), 20000);
975 EXPECT_EQ(Rect::MakeXYWH(10, 20, 200, 100).Area(), 20000);
976 EXPECT_EQ(Rect::MakeXYWH(0, 0, 100, 100).Area(), 10000);
977 EXPECT_EQ(Rect::MakeXYWH(10, 20, 100, 100).Area(), 10000);
978 }

References impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [278/370]

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

Definition at line 2107 of file rect_unittests.cc.

2107 {
2108 auto check_nans = [](const Rect& rect, const Point& point,
2109 const std::string& label) {
2110 ASSERT_TRUE(rect.IsFinite()) << label;
2111 ASSERT_TRUE(point.IsFinite()) << label;
2112
2113 for (int i = 1; i < 16; i++) {
2114 EXPECT_FALSE(swap_nan(rect, i).Contains(point))
2115 << label << ", index = " << i;
2116 for (int j = 1; j < 4; j++) {
2117 EXPECT_FALSE(swap_nan(rect, i).Contains(swap_nan(point, j)))
2118 << label << ", indices = " << i << ", " << j;
2119 }
2120 }
2121 };
2122
2123 auto check_empty_flips = [](const Rect& rect, const Point& point,
2124 const std::string& label) {
2125 ASSERT_FALSE(rect.IsEmpty());
2126
2127 EXPECT_FALSE(flip_lr(rect).Contains(point)) << label;
2128 EXPECT_FALSE(flip_tb(rect).Contains(point)) << label;
2129 EXPECT_FALSE(flip_lrtb(rect).Contains(point)) << label;
2130 };
2131
2132 auto test_inside = [&check_nans, &check_empty_flips](const Rect& rect,
2133 const Point& point) {
2134 ASSERT_FALSE(rect.IsEmpty()) << rect;
2135
2136 std::stringstream stream;
2137 stream << rect << " contains " << point;
2138 auto label = stream.str();
2139
2140 EXPECT_TRUE(rect.Contains(point)) << label;
2141 check_empty_flips(rect, point, label);
2142 check_nans(rect, point, label);
2143 };
2144
2145 auto test_outside = [&check_nans, &check_empty_flips](const Rect& rect,
2146 const Point& point) {
2147 ASSERT_FALSE(rect.IsEmpty()) << rect;
2148
2149 std::stringstream stream;
2150 stream << rect << " contains " << point;
2151 auto label = stream.str();
2152
2153 EXPECT_FALSE(rect.Contains(point)) << label;
2154 check_empty_flips(rect, point, label);
2155 check_nans(rect, point, label);
2156 };
2157
2158 {
2159 // Origin is inclusive
2160 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2161 auto p = Point(100, 100);
2162
2163 test_inside(r, p);
2164 }
2165 {
2166 // Size is exclusive
2167 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2168 auto p = Point(200, 200);
2169
2170 test_outside(r, p);
2171 }
2172 {
2173 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2174 auto p = Point(99, 99);
2175
2176 test_outside(r, p);
2177 }
2178 {
2179 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2180 auto p = Point(199, 199);
2181
2182 test_inside(r, p);
2183 }
2184
2185 {
2186 auto r = Rect::MakeMaximum();
2187 auto p = Point(199, 199);
2188
2189 test_inside(r, p);
2190 }
2191 }

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

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

Definition at line 2262 of file rect_unittests.cc.

2262 {
2263 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
2264 ASSERT_TRUE(a.IsFinite()) << label;
2265 ASSERT_TRUE(b.IsFinite()) << label;
2266 ASSERT_FALSE(a.IsEmpty());
2267
2268 for (int i = 1; i < 16; i++) {
2269 // NaN in a produces false
2270 EXPECT_FALSE(swap_nan(a, i).Contains(b)) << label << ", index = " << i;
2271 // NaN in b produces false
2272 EXPECT_TRUE(a.Contains(swap_nan(b, i))) << label << ", index = " << i;
2273 // NaN in both is false
2274 for (int j = 1; j < 16; j++) {
2275 EXPECT_FALSE(swap_nan(a, i).Contains(swap_nan(b, j)))
2276 << label << ", indices = " << i << ", " << j;
2277 }
2278 }
2279 };
2280
2281 auto check_empty_flips = [](const Rect& a, const Rect& b,
2282 const std::string& label) {
2283 ASSERT_FALSE(a.IsEmpty());
2284 // test b rects are allowed to have 0 w/h, but not be backwards
2285 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2286
2287 // unflipped a vs flipped (empty) b yields false
2288 EXPECT_TRUE(a.Contains(flip_lr(b))) << label;
2289 EXPECT_TRUE(a.Contains(flip_tb(b))) << label;
2290 EXPECT_TRUE(a.Contains(flip_lrtb(b))) << label;
2291
2292 // flipped (empty) a vs unflipped b yields false
2293 EXPECT_FALSE(flip_lr(a).Contains(b)) << label;
2294 EXPECT_FALSE(flip_tb(a).Contains(b)) << label;
2295 EXPECT_FALSE(flip_lrtb(a).Contains(b)) << label;
2296
2297 // flipped (empty) a vs flipped (empty) b yields empty
2298 EXPECT_FALSE(flip_lr(a).Contains(flip_lr(b))) << label;
2299 EXPECT_FALSE(flip_tb(a).Contains(flip_tb(b))) << label;
2300 EXPECT_FALSE(flip_lrtb(a).Contains(flip_lrtb(b))) << label;
2301 };
2302
2303 auto test_inside = [&check_nans, &check_empty_flips](const Rect& a,
2304 const Rect& b) {
2305 ASSERT_FALSE(a.IsEmpty()) << a;
2306 // test b rects are allowed to have 0 w/h, but not be backwards
2307 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2308
2309 std::stringstream stream;
2310 stream << a << " contains " << b;
2311 auto label = stream.str();
2312
2313 EXPECT_TRUE(a.Contains(b)) << label;
2314 check_empty_flips(a, b, label);
2315 check_nans(a, b, label);
2316 };
2317
2318 auto test_not_inside = [&check_nans, &check_empty_flips](const Rect& a,
2319 const Rect& b) {
2320 ASSERT_FALSE(a.IsEmpty()) << a;
2321 // If b was empty, it would be contained and should not be tested with
2322 // this function - use |test_inside| instead.
2323 ASSERT_FALSE(b.IsEmpty()) << b;
2324
2325 std::stringstream stream;
2326 stream << a << " contains " << b;
2327 auto label = stream.str();
2328
2329 EXPECT_FALSE(a.Contains(b)) << label;
2330 check_empty_flips(a, b, label);
2331 check_nans(a, b, label);
2332 };
2333
2334 {
2335 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2336
2337 test_inside(a, a);
2338 }
2339 {
2340 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2341 auto b = Rect::MakeXYWH(0, 0, 0, 0);
2342
2343 test_inside(a, b);
2344 }
2345 {
2346 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2347 auto b = Rect::MakeXYWH(150, 150, 20, 20);
2348
2349 test_inside(a, b);
2350 }
2351 {
2352 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2353 auto b = Rect::MakeXYWH(150, 150, 100, 100);
2354
2355 test_not_inside(a, b);
2356 }
2357 {
2358 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2359 auto b = Rect::MakeXYWH(50, 50, 100, 100);
2360
2361 test_not_inside(a, b);
2362 }
2363 {
2364 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2365 auto b = Rect::MakeXYWH(0, 0, 300, 300);
2366
2367 test_not_inside(a, b);
2368 }
2369 {
2370 auto a = Rect::MakeMaximum();
2371 auto b = Rect::MakeXYWH(0, 0, 300, 300);
2372
2373 test_inside(a, b);
2374 }
2375 }

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

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

Definition at line 623 of file rect_unittests.cc.

623 {
624 // Using fractional-power-of-2 friendly values for equality tests
625 Rect rect = Rect::MakeLTRB(5.125f, 10.25f, 20.625f, 25.375f);
626 Rect copy = rect;
627
628 EXPECT_EQ(rect, copy);
629 EXPECT_EQ(copy.GetLeft(), 5.125f);
630 EXPECT_EQ(copy.GetTop(), 10.25f);
631 EXPECT_EQ(copy.GetRight(), 20.625f);
632 EXPECT_EQ(copy.GetBottom(), 25.375f);
633 EXPECT_EQ(copy.GetX(), 5.125f);
634 EXPECT_EQ(copy.GetY(), 10.25f);
635 EXPECT_EQ(copy.GetWidth(), 15.5f);
636 EXPECT_EQ(copy.GetHeight(), 15.125f);
637 EXPECT_FALSE(copy.IsEmpty());
638 EXPECT_TRUE(copy.IsFinite());
639 }

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

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

Definition at line 2470 of file rect_unittests.cc.

2470 {
2471 Rect cull_rect = Rect::MakeLTRB(20, 20, 40, 40);
2472
2473 auto check_nans = [&cull_rect](const Rect& diff_rect,
2474 const std::string& label) {
2475 EXPECT_TRUE(cull_rect.IsFinite()) << label;
2476 EXPECT_TRUE(diff_rect.IsFinite()) << label;
2477
2478 for (int i = 1; i < 16; i++) {
2479 // NaN in cull_rect produces empty
2480 EXPECT_FALSE(swap_nan(cull_rect, i).Cutout(diff_rect).has_value())
2481 << label << ", index " << i;
2482 EXPECT_EQ(swap_nan(cull_rect, i).CutoutOrEmpty(diff_rect), Rect())
2483 << label << ", index " << i;
2484
2485 // NaN in diff_rect is nop
2486 EXPECT_TRUE(cull_rect.Cutout(swap_nan(diff_rect, i)).has_value())
2487 << label << ", index " << i;
2488 EXPECT_EQ(cull_rect.CutoutOrEmpty(swap_nan(diff_rect, i)), cull_rect)
2489 << label << ", index " << i;
2490
2491 for (int j = 1; j < 16; j++) {
2492 // NaN in both is also empty
2493 EXPECT_FALSE(
2494 swap_nan(cull_rect, i).Cutout(swap_nan(diff_rect, j)).has_value())
2495 << label << ", indices " << i << ", " << j;
2496 EXPECT_EQ(swap_nan(cull_rect, i).CutoutOrEmpty(swap_nan(diff_rect, j)),
2497 Rect())
2498 << label << ", indices " << i << ", " << j;
2499 }
2500 }
2501 };
2502
2503 auto check_empty_flips = [&cull_rect](const Rect& diff_rect,
2504 const std::string& label) {
2505 EXPECT_FALSE(cull_rect.IsEmpty()) << label;
2506 EXPECT_FALSE(diff_rect.IsEmpty()) << label;
2507
2508 // unflipped cull_rect vs flipped(empty) diff_rect
2509 // == cull_rect
2510 EXPECT_TRUE(cull_rect.Cutout(flip_lr(diff_rect)).has_value()) << label;
2511 EXPECT_EQ(cull_rect.Cutout(flip_lr(diff_rect)), cull_rect) << label;
2512 EXPECT_TRUE(cull_rect.Cutout(flip_tb(diff_rect)).has_value()) << label;
2513 EXPECT_EQ(cull_rect.Cutout(flip_tb(diff_rect)), cull_rect) << label;
2514 EXPECT_TRUE(cull_rect.Cutout(flip_lrtb(diff_rect)).has_value()) << label;
2515 EXPECT_EQ(cull_rect.Cutout(flip_lrtb(diff_rect)), cull_rect) << label;
2516
2517 // flipped(empty) cull_rect vs unflipped diff_rect
2518 // == empty
2519 EXPECT_FALSE(flip_lr(cull_rect).Cutout(diff_rect).has_value()) << label;
2520 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(diff_rect), Rect()) << label;
2521 EXPECT_FALSE(flip_tb(cull_rect).Cutout(diff_rect).has_value()) << label;
2522 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(diff_rect), Rect()) << label;
2523 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(diff_rect).has_value()) << label;
2524 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(diff_rect), Rect()) << label;
2525
2526 // flipped(empty) cull_rect vs flipped(empty) diff_rect
2527 // == empty
2528 EXPECT_FALSE(flip_lr(cull_rect).Cutout(flip_lr(diff_rect)).has_value())
2529 << label;
2530 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(flip_lr(diff_rect)), Rect())
2531 << label;
2532 EXPECT_FALSE(flip_tb(cull_rect).Cutout(flip_tb(diff_rect)).has_value())
2533 << label;
2534 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(flip_tb(diff_rect)), Rect())
2535 << label;
2536 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(flip_lrtb(diff_rect)).has_value())
2537 << label;
2538 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(flip_lrtb(diff_rect)), Rect())
2539 << label;
2540 };
2541
2542 auto non_reducing = [&cull_rect, &check_empty_flips, &check_nans](
2543 const Rect& diff_rect, const std::string& label) {
2544 EXPECT_EQ(cull_rect.Cutout(diff_rect), cull_rect) << label;
2545 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), cull_rect) << label;
2546 check_empty_flips(diff_rect, label);
2547 check_nans(diff_rect, label);
2548 };
2549
2550 auto reducing = [&cull_rect, &check_empty_flips, &check_nans](
2551 const Rect& diff_rect, const Rect& result_rect,
2552 const std::string& label) {
2553 EXPECT_TRUE(!result_rect.IsEmpty());
2554 EXPECT_EQ(cull_rect.Cutout(diff_rect), result_rect) << label;
2555 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), result_rect) << label;
2556 check_empty_flips(diff_rect, label);
2557 check_nans(diff_rect, label);
2558 };
2559
2560 auto emptying = [&cull_rect, &check_empty_flips, &check_nans](
2561 const Rect& diff_rect, const std::string& label) {
2562 EXPECT_FALSE(cull_rect.Cutout(diff_rect).has_value()) << label;
2563 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), Rect()) << label;
2564 check_empty_flips(diff_rect, label);
2565 check_nans(diff_rect, label);
2566 };
2567
2568 // Skim the corners and edge
2569 non_reducing(Rect::MakeLTRB(10, 10, 20, 20), "outside UL corner");
2570 non_reducing(Rect::MakeLTRB(20, 10, 40, 20), "Above");
2571 non_reducing(Rect::MakeLTRB(40, 10, 50, 20), "outside UR corner");
2572 non_reducing(Rect::MakeLTRB(40, 20, 50, 40), "Right");
2573 non_reducing(Rect::MakeLTRB(40, 40, 50, 50), "outside LR corner");
2574 non_reducing(Rect::MakeLTRB(20, 40, 40, 50), "Below");
2575 non_reducing(Rect::MakeLTRB(10, 40, 20, 50), "outside LR corner");
2576 non_reducing(Rect::MakeLTRB(10, 20, 20, 40), "Left");
2577
2578 // Overlap corners
2579 non_reducing(Rect::MakeLTRB(15, 15, 25, 25), "covering UL corner");
2580 non_reducing(Rect::MakeLTRB(35, 15, 45, 25), "covering UR corner");
2581 non_reducing(Rect::MakeLTRB(35, 35, 45, 45), "covering LR corner");
2582 non_reducing(Rect::MakeLTRB(15, 35, 25, 45), "covering LL corner");
2583
2584 // Overlap edges, but not across an entire side
2585 non_reducing(Rect::MakeLTRB(20, 15, 39, 25), "Top edge left-biased");
2586 non_reducing(Rect::MakeLTRB(21, 15, 40, 25), "Top edge, right biased");
2587 non_reducing(Rect::MakeLTRB(35, 20, 45, 39), "Right edge, top-biased");
2588 non_reducing(Rect::MakeLTRB(35, 21, 45, 40), "Right edge, bottom-biased");
2589 non_reducing(Rect::MakeLTRB(20, 35, 39, 45), "Bottom edge, left-biased");
2590 non_reducing(Rect::MakeLTRB(21, 35, 40, 45), "Bottom edge, right-biased");
2591 non_reducing(Rect::MakeLTRB(15, 20, 25, 39), "Left edge, top-biased");
2592 non_reducing(Rect::MakeLTRB(15, 21, 25, 40), "Left edge, bottom-biased");
2593
2594 // Slice all the way through the middle
2595 non_reducing(Rect::MakeLTRB(25, 15, 35, 45), "Vertical interior slice");
2596 non_reducing(Rect::MakeLTRB(15, 25, 45, 35), "Horizontal interior slice");
2597
2598 // Slice off each edge
2599 reducing(Rect::MakeLTRB(20, 15, 40, 25), //
2600 Rect::MakeLTRB(20, 25, 40, 40), //
2601 "Slice off top");
2602 reducing(Rect::MakeLTRB(35, 20, 45, 40), //
2603 Rect::MakeLTRB(20, 20, 35, 40), //
2604 "Slice off right");
2605 reducing(Rect::MakeLTRB(20, 35, 40, 45), //
2606 Rect::MakeLTRB(20, 20, 40, 35), //
2607 "Slice off bottom");
2608 reducing(Rect::MakeLTRB(15, 20, 25, 40), //
2609 Rect::MakeLTRB(25, 20, 40, 40), //
2610 "Slice off left");
2611
2612 // cull rect contains diff rect
2613 non_reducing(Rect::MakeLTRB(21, 21, 39, 39), "Contained, non-covering");
2614
2615 // cull rect equals diff rect
2616 emptying(cull_rect, "Perfectly covering");
2617
2618 // diff rect contains cull rect
2619 emptying(Rect::MakeLTRB(15, 15, 45, 45), "Smothering");
2620 }

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

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

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

Definition at line 2812 of file rect_unittests.cc.

2812 {
2813 auto r = Rect::MakeLTRB(1, 2, 3, 4);
2814
2815 EXPECT_EQ(r.GetLeft(), 1);
2816 EXPECT_EQ(r.GetTop(), 2);
2817 EXPECT_EQ(r.GetRight(), 3);
2818 EXPECT_EQ(r.GetBottom(), 4);
2819
2820 EXPECT_POINT_NEAR(r.GetLeftTop(), Point(1, 2));
2821 EXPECT_POINT_NEAR(r.GetRightTop(), Point(3, 2));
2822 EXPECT_POINT_NEAR(r.GetLeftBottom(), Point(1, 4));
2823 EXPECT_POINT_NEAR(r.GetRightBottom(), Point(3, 4));
2824 }

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

## ◆ TEST() [284/370]

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

Definition at line 764 of file rect_unittests.cc.

764 {
765 Rect rect = Rect::MakeLTRB(50, 50, 100, 100);
766
767 auto test = [&rect](Scalar l, Scalar t, Scalar r, Scalar b,
768 const std::string& label) {
769 EXPECT_FALSE(rect.IntersectsWithRect(Rect::MakeLTRB(l, b, r, t)))
770 << label << " with Top/Bottom swapped";
771 EXPECT_FALSE(rect.IntersectsWithRect(Rect::MakeLTRB(r, b, l, t)))
772 << label << " with Left/Right swapped";
773 EXPECT_FALSE(rect.IntersectsWithRect(Rect::MakeLTRB(r, t, l, b)))
774 << label << " with all sides swapped";
775 };
776
777 test(20, 20, 30, 30, "Above and Left");
778 test(70, 20, 80, 30, "Above");
779 test(120, 20, 130, 30, "Above and Right");
780 test(120, 70, 130, 80, "Right");
781 test(120, 120, 130, 130, "Below and Right");
782 test(70, 120, 80, 130, "Below");
783 test(20, 120, 30, 130, "Below and Left");
784 test(20, 70, 30, 80, "Left");
785
786 test(70, 70, 80, 80, "Inside");
787
788 test(40, 70, 60, 80, "Straddling Left");
789 test(70, 40, 80, 60, "Straddling Top");
790 test(90, 70, 110, 80, "Straddling Right");
791 test(70, 90, 80, 110, "Straddling Bottom");
792 }

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

## ◆ TEST() [285/370]

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

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

Definition at line 1205 of file rect_unittests.cc.

1205 {
1206 auto rect = Rect::MakeLTRB(100, 100, 200, 200);
1207
1208 // Expand(T amount)
1209 EXPECT_EQ(rect.Expand(10), Rect::MakeLTRB(90, 90, 210, 210));
1210 EXPECT_EQ(rect.Expand(-10), Rect::MakeLTRB(110, 110, 190, 190));
1211
1212 // Expand(amount, amount)
1213 EXPECT_EQ(rect.Expand(10, 10), Rect::MakeLTRB(90, 90, 210, 210));
1214 EXPECT_EQ(rect.Expand(10, -10), Rect::MakeLTRB(90, 110, 210, 190));
1215 EXPECT_EQ(rect.Expand(-10, 10), Rect::MakeLTRB(110, 90, 190, 210));
1216 EXPECT_EQ(rect.Expand(-10, -10), Rect::MakeLTRB(110, 110, 190, 190));
1217
1218 // Expand(amount, amount, amount, amount)
1219 EXPECT_EQ(rect.Expand(10, 20, 30, 40), Rect::MakeLTRB(90, 80, 230, 240));
1220 EXPECT_EQ(rect.Expand(-10, 20, 30, 40), Rect::MakeLTRB(110, 80, 230, 240));
1221 EXPECT_EQ(rect.Expand(10, -20, 30, 40), Rect::MakeLTRB(90, 120, 230, 240));
1222 EXPECT_EQ(rect.Expand(10, 20, -30, 40), Rect::MakeLTRB(90, 80, 170, 240));
1223 EXPECT_EQ(rect.Expand(10, 20, 30, -40), Rect::MakeLTRB(90, 80, 230, 160));
1224
1225 // Expand(Point amount)
1226 EXPECT_EQ(rect.Expand(Point{10, 10}), Rect::MakeLTRB(90, 90, 210, 210));
1227 EXPECT_EQ(rect.Expand(Point{10, -10}), Rect::MakeLTRB(90, 110, 210, 190));
1228 EXPECT_EQ(rect.Expand(Point{-10, 10}), Rect::MakeLTRB(110, 90, 190, 210));
1229 EXPECT_EQ(rect.Expand(Point{-10, -10}), Rect::MakeLTRB(110, 110, 190, 190));
1230
1231 // Expand(Size amount)
1232 EXPECT_EQ(rect.Expand(Size{10, 10}), Rect::MakeLTRB(90, 90, 210, 210));
1233 EXPECT_EQ(rect.Expand(Size{10, -10}), Rect::MakeLTRB(90, 110, 210, 190));
1234 EXPECT_EQ(rect.Expand(Size{-10, 10}), Rect::MakeLTRB(110, 90, 190, 210));
1235 EXPECT_EQ(rect.Expand(Size{-10, -10}), Rect::MakeLTRB(110, 110, 190, 190));
1236 }

References impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [287/370]

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

Definition at line 609 of file rect_unittests.cc.

609 {
610 EXPECT_EQ(Rect(Rect::MakeXYWH(2, 3, 7, 15)),
611 Rect::MakeXYWH(2.0, 3.0, 7.0, 15.0));
612 EXPECT_EQ(Rect(Rect::MakeLTRB(2, 3, 7, 15)),
613 Rect::MakeLTRB(2.0, 3.0, 7.0, 15.0));
614 }

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

## ◆ TEST() [288/370]

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

Definition at line 989 of file rect_unittests.cc.

989 {
990 {
991 // Checks for expected matrix values
992
993 auto r = Rect::MakeXYWH(100, 200, 200, 400);
994
995 EXPECT_EQ(r.GetNormalizingTransform(),
996 Matrix::MakeScale({0.005, 0.0025, 1.0}) *
997 Matrix::MakeTranslation({-100, -200}));
998 }
999
1000 {
1001 // Checks for expected transform of points relative to the rect
1002
1003 auto r = Rect::MakeLTRB(300, 500, 400, 700);
1004 auto m = r.GetNormalizingTransform();
1005
1006 // The 4 corners of the rect => (0, 0) to (1, 1)
1007 EXPECT_EQ(m * Point(300, 500), Point(0, 0));
1008 EXPECT_EQ(m * Point(400, 500), Point(1, 0));
1009 EXPECT_EQ(m * Point(400, 700), Point(1, 1));
1010 EXPECT_EQ(m * Point(300, 700), Point(0, 1));
1011
1012 // The center => (0.5, 0.5)
1013 EXPECT_EQ(m * Point(350, 600), Point(0.5, 0.5));
1014
1015 // Outside the 4 corners => (-1, -1) to (2, 2)
1016 EXPECT_EQ(m * Point(200, 300), Point(-1, -1));
1017 EXPECT_EQ(m * Point(500, 300), Point(2, -1));
1018 EXPECT_EQ(m * Point(500, 900), Point(2, 2));
1019 EXPECT_EQ(m * Point(200, 900), Point(-1, 2));
1020 }
1021
1022 {
1023 // Checks for behavior with empty rects
1024
1025 auto zero = Matrix::MakeScale({0.0, 0.0, 1.0});
1026
1027 // Empty for width and/or height == 0
1028 EXPECT_EQ(Rect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
1029 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
1030 EXPECT_EQ(Rect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
1031
1032 // Empty for width and/or height < 0
1033 EXPECT_EQ(Rect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
1034 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
1035 EXPECT_EQ(Rect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
1036 }
1037
1038 {
1039 // Checks for behavior with non-finite rects
1040
1041 auto z = Matrix::MakeScale({0.0, 0.0, 1.0});
1042 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
1043 auto inf = std::numeric_limits<Scalar>::infinity();
1044
1045 // Non-finite for width and/or height == nan
1046 EXPECT_EQ(Rect::MakeXYWH(10, 10, nan, 10).GetNormalizingTransform(), z);
1047 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, nan).GetNormalizingTransform(), z);
1048 EXPECT_EQ(Rect::MakeXYWH(10, 10, nan, nan).GetNormalizingTransform(), z);
1049
1050 // Non-finite for width and/or height == inf
1051 EXPECT_EQ(Rect::MakeXYWH(10, 10, inf, 10).GetNormalizingTransform(), z);
1052 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, inf).GetNormalizingTransform(), z);
1053 EXPECT_EQ(Rect::MakeXYWH(10, 10, inf, inf).GetNormalizingTransform(), z);
1054
1055 // Non-finite for width and/or height == -inf
1056 EXPECT_EQ(Rect::MakeXYWH(10, 10, -inf, 10).GetNormalizingTransform(), z);
1057 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, -inf).GetNormalizingTransform(), z);
1058 EXPECT_EQ(Rect::MakeXYWH(10, 10, -inf, -inf).GetNormalizingTransform(), z);
1059
1060 // Non-finite for origin X and/or Y == nan
1061 EXPECT_EQ(Rect::MakeXYWH(nan, 10, 10, 10).GetNormalizingTransform(), z);
1062 EXPECT_EQ(Rect::MakeXYWH(10, nan, 10, 10).GetNormalizingTransform(), z);
1063 EXPECT_EQ(Rect::MakeXYWH(nan, nan, 10, 10).GetNormalizingTransform(), z);
1064
1065 // Non-finite for origin X and/or Y == inf
1066 EXPECT_EQ(Rect::MakeXYWH(inf, 10, 10, 10).GetNormalizingTransform(), z);
1067 EXPECT_EQ(Rect::MakeXYWH(10, inf, 10, 10).GetNormalizingTransform(), z);
1068 EXPECT_EQ(Rect::MakeXYWH(inf, inf, 10, 10).GetNormalizingTransform(), z);
1069
1070 // Non-finite for origin X and/or Y == -inf
1071 EXPECT_EQ(Rect::MakeXYWH(-inf, 10, 10, 10).GetNormalizingTransform(), z);
1072 EXPECT_EQ(Rect::MakeXYWH(10, -inf, 10, 10).GetNormalizingTransform(), z);
1073 EXPECT_EQ(Rect::MakeXYWH(-inf, -inf, 10, 10).GetNormalizingTransform(), z);
1074 }
1075 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [289/370]

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

Definition at line 2741 of file rect_unittests.cc.

2741 {
2742 {
2743 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
2744 auto points = r.GetPoints();
2745 EXPECT_POINT_NEAR(points[0], Point(100, 200));
2746 EXPECT_POINT_NEAR(points[1], Point(400, 200));
2747 EXPECT_POINT_NEAR(points[2], Point(100, 600));
2748 EXPECT_POINT_NEAR(points[3], Point(400, 600));
2749 }
2750
2751 {
2752 Rect r = Rect::MakeMaximum();
2753 auto points = r.GetPoints();
2754 EXPECT_EQ(points[0], Point(std::numeric_limits<float>::lowest(),
2755 std::numeric_limits<float>::lowest()));
2756 EXPECT_EQ(points[1], Point(std::numeric_limits<float>::max(),
2757 std::numeric_limits<float>::lowest()));
2758 EXPECT_EQ(points[2], Point(std::numeric_limits<float>::lowest(),
2759 std::numeric_limits<float>::max()));
2760 EXPECT_EQ(points[3], Point(std::numeric_limits<float>::max(),
2761 std::numeric_limits<float>::max()));
2762 }
2763 }

References EXPECT_POINT_NEAR, impeller::TRect< T >::GetPoints(), impeller::TRect< Scalar >::MakeMaximum(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [290/370]

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

Definition at line 2798 of file rect_unittests.cc.

2798 {
2799 {
2800 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
2801 auto actual = r.GetPositive();
2802 EXPECT_RECT_NEAR(r, actual);
2803 }
2804 {
2805 Rect r = Rect::MakeXYWH(100, 200, -100, -100);
2806 auto actual = r.GetPositive();
2807 Rect expected = Rect::MakeXYWH(0, 100, 100, 100);
2808 EXPECT_RECT_NEAR(expected, actual);
2809 }
2810 }

References EXPECT_RECT_NEAR, impeller::TRect< T >::GetPositive(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [291/370]

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

Definition at line 2772 of file rect_unittests.cc.

2772 {
2773 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
2774 auto points = r.GetTransformedPoints(Matrix::MakeTranslation({10, 20}));
2775 EXPECT_POINT_NEAR(points[0], Point(110, 220));
2776 EXPECT_POINT_NEAR(points[1], Point(410, 220));
2777 EXPECT_POINT_NEAR(points[2], Point(110, 620));
2778 EXPECT_POINT_NEAR(points[3], Point(410, 620));
2779 }

References EXPECT_POINT_NEAR, impeller::TRect< T >::GetTransformedPoints(), impeller::Matrix::MakeTranslation(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [292/370]

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

Definition at line 1580 of file rect_unittests.cc.

1580 {
1581 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1582 ASSERT_TRUE(a.IsFinite()) << label;
1583 ASSERT_TRUE(b.IsFinite()) << label;
1584
1585 for (int i = 1; i < 16; i++) {
1586 // NaN in a produces empty
1587 EXPECT_FALSE(swap_nan(a, i).Intersection(b).has_value())
1588 << label << ", index = " << i;
1589 // NaN in b produces empty
1590 EXPECT_FALSE(a.Intersection(swap_nan(b, i)).has_value())
1591 << label << ", index = " << i;
1592 // NaN in both is empty
1593 for (int j = 1; j < 16; j++) {
1594 EXPECT_FALSE(swap_nan(a, i).Intersection(swap_nan(b, j)).has_value())
1595 << label << ", indices = " << i << ", " << j;
1596 }
1597 }
1598 };
1599
1600 auto check_empty_flips = [](const Rect& a, const Rect& b,
1601 const std::string& label) {
1602 ASSERT_FALSE(a.IsEmpty());
1603 // b is allowed to be empty
1604
1605 // unflipped a vs flipped (empty) b yields a
1606 EXPECT_FALSE(a.Intersection(flip_lr(b)).has_value()) << label;
1607 EXPECT_FALSE(a.Intersection(flip_tb(b)).has_value()) << label;
1608 EXPECT_FALSE(a.Intersection(flip_lrtb(b)).has_value()) << label;
1609
1610 // flipped (empty) a vs unflipped b yields b
1611 EXPECT_FALSE(flip_lr(a).Intersection(b).has_value()) << label;
1612 EXPECT_FALSE(flip_tb(a).Intersection(b).has_value()) << label;
1613 EXPECT_FALSE(flip_lrtb(a).Intersection(b).has_value()) << label;
1614
1615 // flipped (empty) a vs flipped (empty) b yields empty
1616 EXPECT_FALSE(flip_lr(a).Intersection(flip_lr(b)).has_value()) << label;
1617 EXPECT_FALSE(flip_tb(a).Intersection(flip_tb(b)).has_value()) << label;
1618 EXPECT_FALSE(flip_lrtb(a).Intersection(flip_lrtb(b)).has_value()) << label;
1619 };
1620
1621 auto test_non_empty = [&check_nans, &check_empty_flips](
1622 const Rect& a, const Rect& b, const Rect& result) {
1623 ASSERT_FALSE(a.IsEmpty()) << a;
1624 // b is allowed to be empty
1625
1626 std::stringstream stream;
1627 stream << a << " union " << b;
1628 auto label = stream.str();
1629
1630 EXPECT_TRUE(a.Intersection(b).has_value()) << label;
1631 EXPECT_TRUE(b.Intersection(a).has_value()) << label;
1632 EXPECT_EQ(a.Intersection(b), result) << label;
1633 EXPECT_EQ(b.Intersection(a), result) << label;
1634 check_empty_flips(a, b, label);
1635 check_nans(a, b, label);
1636 };
1637
1638 auto test_empty = [&check_nans, &check_empty_flips](const Rect& a,
1639 const Rect& b) {
1640 ASSERT_FALSE(a.IsEmpty()) << a;
1641 // b is allowed to be empty
1642
1643 std::stringstream stream;
1644 stream << a << " union " << b;
1645 auto label = stream.str();
1646
1647 EXPECT_FALSE(a.Intersection(b).has_value()) << label;
1648 EXPECT_FALSE(b.Intersection(a).has_value()) << label;
1649 check_empty_flips(a, b, label);
1650 check_nans(a, b, label);
1651 };
1652
1653 {
1654 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1655 auto b = Rect::MakeXYWH(0, 0, 0, 0);
1656
1657 test_empty(a, b);
1658 }
1659
1660 {
1661 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1662 auto b = Rect::MakeXYWH(10, 10, 0, 0);
1663
1664 test_empty(a, b);
1665 }
1666
1667 {
1668 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1669 auto b = Rect::MakeXYWH(10, 10, 100, 100);
1670 auto expected = Rect::MakeXYWH(10, 10, 90, 90);
1671
1672 test_non_empty(a, b, expected);
1673 }
1674
1675 {
1676 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1677 auto b = Rect::MakeXYWH(100, 100, 100, 100);
1678
1679 test_empty(a, b);
1680 }
1681
1682 {
1683 auto a = Rect::MakeMaximum();
1684 auto b = Rect::MakeXYWH(10, 10, 300, 300);
1685
1686 test_non_empty(a, b, b);
1687 }
1688
1689 {
1690 auto a = Rect::MakeMaximum();
1691 auto b = Rect::MakeMaximum();
1692
1693 test_non_empty(a, b, Rect::MakeMaximum());
1694 }
1695 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::Intersection(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< Scalar >::MakeXYWH(), and swap_nan().

## ◆ TEST() [293/370]

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

Definition at line 1902 of file rect_unittests.cc.

1902 {
1903 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1904 ASSERT_TRUE(a.IsFinite()) << label;
1905 ASSERT_TRUE(b.IsFinite()) << label;
1906
1907 for (int i = 1; i < 16; i++) {
1908 // NaN in a produces b
1909 EXPECT_FALSE(swap_nan(a, i).IntersectsWithRect(b))
1910 << label << ", index = " << i;
1911 // NaN in b produces a
1912 EXPECT_FALSE(a.IntersectsWithRect(swap_nan(b, i)))
1913 << label << ", index = " << i;
1914 // NaN in both is empty
1915 for (int j = 1; j < 16; j++) {
1916 EXPECT_FALSE(swap_nan(a, i).IntersectsWithRect(swap_nan(b, j)))
1917 << label << ", indices = " << i << ", " << j;
1918 }
1919 }
1920 };
1921
1922 auto check_empty_flips = [](const Rect& a, const Rect& b,
1923 const std::string& label) {
1924 ASSERT_FALSE(a.IsEmpty());
1925 // b is allowed to be empty
1926
1927 // unflipped a vs flipped (empty) b yields a
1928 EXPECT_FALSE(a.IntersectsWithRect(flip_lr(b))) << label;
1929 EXPECT_FALSE(a.IntersectsWithRect(flip_tb(b))) << label;
1930 EXPECT_FALSE(a.IntersectsWithRect(flip_lrtb(b))) << label;
1931
1932 // flipped (empty) a vs unflipped b yields b
1933 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(b)) << label;
1934 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(b)) << label;
1935 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(b)) << label;
1936
1937 // flipped (empty) a vs flipped (empty) b yields empty
1938 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(flip_lr(b))) << label;
1939 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(flip_tb(b))) << label;
1940 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(flip_lrtb(b))) << label;
1941 };
1942
1943 auto test_non_empty = [&check_nans, &check_empty_flips](const Rect& a,
1944 const Rect& b) {
1945 ASSERT_FALSE(a.IsEmpty()) << a;
1946 // b is allowed to be empty
1947
1948 std::stringstream stream;
1949 stream << a << " union " << b;
1950 auto label = stream.str();
1951
1952 EXPECT_TRUE(a.IntersectsWithRect(b)) << label;
1953 EXPECT_TRUE(b.IntersectsWithRect(a)) << label;
1954 check_empty_flips(a, b, label);
1955 check_nans(a, b, label);
1956 };
1957
1958 auto test_empty = [&check_nans, &check_empty_flips](const Rect& a,
1959 const Rect& b) {
1960 ASSERT_FALSE(a.IsEmpty()) << a;
1961 // b is allowed to be empty
1962
1963 std::stringstream stream;
1964 stream << a << " union " << b;
1965 auto label = stream.str();
1966
1967 EXPECT_FALSE(a.IntersectsWithRect(b)) << label;
1968 EXPECT_FALSE(b.IntersectsWithRect(a)) << label;
1969 check_empty_flips(a, b, label);
1970 check_nans(a, b, label);
1971 };
1972
1973 {
1974 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1975 auto b = Rect::MakeXYWH(0, 0, 0, 0);
1976
1977 test_empty(a, b);
1978 }
1979
1980 {
1981 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1982 auto b = Rect::MakeXYWH(10, 10, 0, 0);
1983
1984 test_empty(a, b);
1985 }
1986
1987 {
1988 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1989 auto b = Rect::MakeXYWH(10, 10, 100, 100);
1990
1991 test_non_empty(a, b);
1992 }
1993
1994 {
1995 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1996 auto b = Rect::MakeXYWH(100, 100, 100, 100);
1997
1998 test_empty(a, b);
1999 }
2000
2001 {
2002 auto a = Rect::MakeMaximum();
2003 auto b = Rect::MakeXYWH(10, 10, 100, 100);
2004
2005 test_non_empty(a, b);
2006 }
2007
2008 {
2009 auto a = Rect::MakeMaximum();
2010 auto b = Rect::MakeMaximum();
2011
2012 test_non_empty(a, b);
2013 }
2014 }

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

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

Definition at line 575 of file rect_unittests.cc.

575 {
576 Rect rect = Rect::MakeMaximum();
577 auto inf = std::numeric_limits<Scalar>::infinity();
578 auto min = std::numeric_limits<Scalar>::lowest();
579 auto max = std::numeric_limits<Scalar>::max();
580
581 EXPECT_EQ(rect.GetLeft(), min);
582 EXPECT_EQ(rect.GetTop(), min);
583 EXPECT_EQ(rect.GetRight(), max);
584 EXPECT_EQ(rect.GetBottom(), max);
585 EXPECT_EQ(rect.GetX(), min);
586 EXPECT_EQ(rect.GetY(), min);
587 EXPECT_EQ(rect.GetWidth(), inf);
588 EXPECT_EQ(rect.GetHeight(), inf);
589 EXPECT_FALSE(rect.IsEmpty());
590 EXPECT_TRUE(rect.IsFinite());
591 }

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

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

Definition at line 2781 of file rect_unittests.cc.

2781 {
2782 {
2783 std::vector<Point> points{{1, 5}, {4, -1}, {0, 6}};
2784 auto r = Rect::MakePointBounds(points.begin(), points.end());
2785 auto expected = Rect::MakeXYWH(0, -1, 4, 7);
2786 EXPECT_TRUE(r.has_value());
2787 if (r.has_value()) {
2788 EXPECT_RECT_NEAR(r.value(), expected);
2789 }
2790 }
2791 {
2792 std::vector<Point> points;
2793 std::optional<Rect> r = Rect::MakePointBounds(points.begin(), points.end());
2794 EXPECT_FALSE(r.has_value());
2795 }
2796 }

References EXPECT_RECT_NEAR, impeller::TRect< Scalar >::MakePointBounds(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [296/370]

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

Definition at line 545 of file rect_unittests.cc.

545 {
546 {
547 Size s(100, 200);
548 Rect r = Rect::MakeSize(s);
549 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
550 EXPECT_RECT_NEAR(r, expected);
551 }
552
553 {
554 ISize s(100, 200);
555 Rect r = Rect::MakeSize(s);
556 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
557 EXPECT_RECT_NEAR(r, expected);
558 }
559
560 {
561 Size s(100, 200);
562 IRect r = IRect::MakeSize(s);
563 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
564 EXPECT_EQ(r, expected);
565 }
566
567 {
568 ISize s(100, 200);
569 IRect r = IRect::MakeSize(s);
570 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
571 EXPECT_EQ(r, expected);
572 }
573 }

References EXPECT_RECT_NEAR, impeller::TRect< int64_t >::MakeLTRB(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< int64_t >::MakeSize(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST() [297/370]

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

Definition at line 657 of file rect_unittests.cc.

657 {
658 {
659 Rect r = Rect::MakeOriginSize({10, 20}, {50, 40});
660 EXPECT_EQ(r.GetOrigin(), Point(10, 20));
661 EXPECT_EQ(r.GetSize(), Size(50, 40));
662 EXPECT_EQ(r.GetX(), 10);
663 EXPECT_EQ(r.GetY(), 20);
664 EXPECT_EQ(r.GetWidth(), 50);
665 EXPECT_EQ(r.GetHeight(), 40);
666 auto expected_array = std::array<Scalar, 4>{10, 20, 50, 40};
667 EXPECT_EQ(r.GetXYWH(), expected_array);
668 }
669
670 {
671 Rect r = Rect::MakeLTRB(10, 20, 50, 40);
672 EXPECT_EQ(r.GetOrigin(), Point(10, 20));
673 EXPECT_EQ(r.GetSize(), Size(40, 20));
674 EXPECT_EQ(r.GetX(), 10);
675 EXPECT_EQ(r.GetY(), 20);
676 EXPECT_EQ(r.GetWidth(), 40);
677 EXPECT_EQ(r.GetHeight(), 20);
678 auto expected_array = std::array<Scalar, 4>{10, 20, 40, 20};
679 EXPECT_EQ(r.GetXYWH(), expected_array);
680 }
681 }

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

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

Definition at line 339 of file rect_unittests.cc.

339 {
340 auto min = std::numeric_limits<Scalar>::lowest();
341 auto max = std::numeric_limits<Scalar>::max();
342 auto inf = std::numeric_limits<Scalar>::infinity();
343
344 // 8 cases:
345 // finite negative X, max W
346 // ~min X, ~max W
347 // finite negative Y, max H
348 // ~min Y, ~max H
349 // finite positive X, min W
350 // ~min X, ~min W
351 // finite positive Y, min H
352 // ~min Y, ~min H
353
354 // a small finite value subtracted from a max value will remain max
355 // a very large finite value (like min) subtracted from max will go to inf
356
357 {
358 Rect rect = Rect::MakeLTRB(-5.0f, 10.0f, max, 25.0f);
359
360 EXPECT_EQ(rect.GetLeft(), -5.0f);
361 EXPECT_EQ(rect.GetTop(), 10.0f);
362 EXPECT_EQ(rect.GetRight(), max);
363 EXPECT_EQ(rect.GetBottom(), 25.0f);
364 EXPECT_EQ(rect.GetX(), -5.0f);
365 EXPECT_EQ(rect.GetY(), 10.0f);
366 EXPECT_EQ(rect.GetWidth(), max);
367 EXPECT_EQ(rect.GetHeight(), 15.0f);
368 EXPECT_FALSE(rect.IsEmpty());
369 EXPECT_TRUE(rect.IsFinite());
370 }
371
372 {
373 Rect rect = Rect::MakeLTRB(min + 5.0f, 10.0f, max - 5.0f, 25.0f);
374
375 EXPECT_EQ(rect.GetLeft(), min + 5.0f);
376 EXPECT_EQ(rect.GetTop(), 10.0f);
377 EXPECT_EQ(rect.GetRight(), max - 5.0f);
378 EXPECT_EQ(rect.GetBottom(), 25.0f);
379 EXPECT_EQ(rect.GetX(), min + 5.0f);
380 EXPECT_EQ(rect.GetY(), 10.0f);
381 EXPECT_EQ(rect.GetWidth(), inf);
382 EXPECT_EQ(rect.GetHeight(), 15.0f);
383 EXPECT_FALSE(rect.IsEmpty());
384 EXPECT_TRUE(rect.IsFinite());
385 }
386
387 {
388 Rect rect = Rect::MakeLTRB(5.0f, -10.0f, 20.0f, max);
389
390 EXPECT_EQ(rect.GetLeft(), 5.0f);
391 EXPECT_EQ(rect.GetTop(), -10.0f);
392 EXPECT_EQ(rect.GetRight(), 20.0f);
393 EXPECT_EQ(rect.GetBottom(), max);
394 EXPECT_EQ(rect.GetX(), 5.0f);
395 EXPECT_EQ(rect.GetY(), -10.0f);
396 EXPECT_EQ(rect.GetWidth(), 15.0f);
397 EXPECT_EQ(rect.GetHeight(), max);
398 EXPECT_FALSE(rect.IsEmpty());
399 EXPECT_TRUE(rect.IsFinite());
400 }
401
402 {
403 Rect rect = Rect::MakeLTRB(5.0f, min + 10.0f, 20.0f, max - 15.0f);
404
405 EXPECT_EQ(rect.GetLeft(), 5.0f);
406 EXPECT_EQ(rect.GetTop(), min + 10.0f);
407 EXPECT_EQ(rect.GetRight(), 20.0f);
408 EXPECT_EQ(rect.GetBottom(), max - 15.0f);
409 EXPECT_EQ(rect.GetX(), 5.0f);
410 EXPECT_EQ(rect.GetY(), min + 10.0f);
411 EXPECT_EQ(rect.GetWidth(), 15.0f);
412 EXPECT_EQ(rect.GetHeight(), inf);
413 EXPECT_FALSE(rect.IsEmpty());
414 EXPECT_TRUE(rect.IsFinite());
415 }
416
417 {
418 Rect rect = Rect::MakeLTRB(5.0f, 10.0f, min, 25.0f);
419
420 EXPECT_EQ(rect.GetLeft(), 5.0f);
421 EXPECT_EQ(rect.GetTop(), 10.0f);
422 EXPECT_EQ(rect.GetRight(), min);
423 EXPECT_EQ(rect.GetBottom(), 25.0f);
424 EXPECT_EQ(rect.GetX(), 5.0f);
425 EXPECT_EQ(rect.GetY(), 10.0f);
426 EXPECT_EQ(rect.GetWidth(), min);
427 EXPECT_EQ(rect.GetHeight(), 15.0f);
428 EXPECT_TRUE(rect.IsEmpty());
429 EXPECT_TRUE(rect.IsFinite());
430 }
431
432 {
433 Rect rect = Rect::MakeLTRB(max - 5.0f, 10.0f, min + 10.0f, 25.0f);
434
435 EXPECT_EQ(rect.GetLeft(), max - 5.0f);
436 EXPECT_EQ(rect.GetTop(), 10.0f);
437 EXPECT_EQ(rect.GetRight(), min + 10.0f);
438 EXPECT_EQ(rect.GetBottom(), 25.0f);
439 EXPECT_EQ(rect.GetX(), max - 5.0f);
440 EXPECT_EQ(rect.GetY(), 10.0f);
441 EXPECT_EQ(rect.GetWidth(), -inf);
442 EXPECT_EQ(rect.GetHeight(), 15.0f);
443 EXPECT_TRUE(rect.IsEmpty());
444 EXPECT_TRUE(rect.IsFinite());
445 }
446
447 {
448 Rect rect = Rect::MakeLTRB(5.0f, 10.0f, 20.0f, min);
449
450 EXPECT_EQ(rect.GetLeft(), 5.0f);
451 EXPECT_EQ(rect.GetTop(), 10.0f);
452 EXPECT_EQ(rect.GetRight(), 20.0f);
453 EXPECT_EQ(rect.GetBottom(), min);
454 EXPECT_EQ(rect.GetX(), 5.0f);
455 EXPECT_EQ(rect.GetY(), 10.0f);
456 EXPECT_EQ(rect.GetWidth(), 15.0f);
457 EXPECT_EQ(rect.GetHeight(), min);
458 EXPECT_TRUE(rect.IsEmpty());
459 EXPECT_TRUE(rect.IsFinite());
460 }
461
462 {
463 Rect rect = Rect::MakeLTRB(5.0f, max - 5.0f, 20.0f, min + 10.0f);
464
465 EXPECT_EQ(rect.GetLeft(), 5.0f);
466 EXPECT_EQ(rect.GetTop(), max - 5.0f);
467 EXPECT_EQ(rect.GetRight(), 20.0f);
468 EXPECT_EQ(rect.GetBottom(), min + 10.0f);
469 EXPECT_EQ(rect.GetX(), 5.0f);
470 EXPECT_EQ(rect.GetY(), max - 5.0f);
471 EXPECT_EQ(rect.GetWidth(), 15.0f);
472 EXPECT_EQ(rect.GetHeight(), -inf);
473 EXPECT_TRUE(rect.IsEmpty());
474 EXPECT_TRUE(rect.IsFinite());
475 }
476 }

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

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

Definition at line 133 of file rect_unittests.cc.

133 {
134 auto min = std::numeric_limits<Scalar>::lowest();
135 auto max = std::numeric_limits<Scalar>::max();
136 auto inf = std::numeric_limits<Scalar>::infinity();
137
138 // 8 cases:
139 // finite X, max W
140 // max X, max W
141 // finite Y, max H
142 // max Y, max H
143 // finite X, min W
144 // min X, min W
145 // finite Y, min H
146 // min Y, min H
147
148 // a small finite value added to a max value will remain max
149 // a very large finite value (like max) added to max will go to infinity
150
151 {
152 Rect rect = Rect::MakeXYWH(5.0, 10.0f, max, 15.0f);
153
154 EXPECT_EQ(rect.GetLeft(), 5.0f);
155 EXPECT_EQ(rect.GetTop(), 10.0f);
156 EXPECT_EQ(rect.GetRight(), max);
157 EXPECT_EQ(rect.GetBottom(), 25.0f);
158 EXPECT_EQ(rect.GetX(), 5.0f);
159 EXPECT_EQ(rect.GetY(), 10.0f);
160 EXPECT_EQ(rect.GetWidth(), max);
161 EXPECT_EQ(rect.GetHeight(), 15.0f);
162 EXPECT_FALSE(rect.IsEmpty());
163 EXPECT_TRUE(rect.IsFinite());
164 }
165
166 {
167 Rect rect = Rect::MakeXYWH(max, 10.0f, max, 15.0f);
168
169 EXPECT_EQ(rect.GetLeft(), max);
170 EXPECT_EQ(rect.GetTop(), 10.0f);
171 EXPECT_EQ(rect.GetRight(), inf);
172 EXPECT_EQ(rect.GetBottom(), 25.0f);
173 EXPECT_EQ(rect.GetX(), max);
174 EXPECT_EQ(rect.GetY(), 10.0f);
175 EXPECT_EQ(rect.GetWidth(), inf);
176 EXPECT_EQ(rect.GetHeight(), 15.0f);
177 EXPECT_FALSE(rect.IsEmpty());
178 EXPECT_FALSE(rect.IsFinite());
179 }
180
181 {
182 Rect rect = Rect::MakeXYWH(5.0f, 10.0f, 20.0f, max);
183
184 EXPECT_EQ(rect.GetLeft(), 5.0f);
185 EXPECT_EQ(rect.GetTop(), 10.0f);
186 EXPECT_EQ(rect.GetRight(), 25.0f);
187 EXPECT_EQ(rect.GetBottom(), max);
188 EXPECT_EQ(rect.GetX(), 5.0f);
189 EXPECT_EQ(rect.GetY(), 10.0f);
190 EXPECT_EQ(rect.GetWidth(), 20.0f);
191 EXPECT_EQ(rect.GetHeight(), max);
192 EXPECT_FALSE(rect.IsEmpty());
193 EXPECT_TRUE(rect.IsFinite());
194 }
195
196 {
197 Rect rect = Rect::MakeXYWH(5.0f, max, 20.0f, max);
198
199 EXPECT_EQ(rect.GetLeft(), 5.0f);
200 EXPECT_EQ(rect.GetTop(), max);
201 EXPECT_EQ(rect.GetRight(), 25.0f);
202 EXPECT_EQ(rect.GetBottom(), inf);
203 EXPECT_EQ(rect.GetX(), 5.0f);
204 EXPECT_EQ(rect.GetY(), max);
205 EXPECT_EQ(rect.GetWidth(), 20.0f);
206 EXPECT_EQ(rect.GetHeight(), inf);
207 EXPECT_FALSE(rect.IsEmpty());
208 EXPECT_FALSE(rect.IsFinite());
209 }
210
211 {
212 Rect rect = Rect::MakeXYWH(5.0, 10.0f, min, 15.0f);
213
214 EXPECT_EQ(rect.GetLeft(), 5.0f);
215 EXPECT_EQ(rect.GetTop(), 10.0f);
216 EXPECT_EQ(rect.GetRight(), min);
217 EXPECT_EQ(rect.GetBottom(), 25.0f);
218 EXPECT_EQ(rect.GetX(), 5.0f);
219 EXPECT_EQ(rect.GetY(), 10.0f);
220 EXPECT_EQ(rect.GetWidth(), min);
221 EXPECT_EQ(rect.GetHeight(), 15.0f);
222 EXPECT_TRUE(rect.IsEmpty());
223 EXPECT_TRUE(rect.IsFinite());
224 }
225
226 {
227 Rect rect = Rect::MakeXYWH(min, 10.0f, min, 15.0f);
228
229 EXPECT_EQ(rect.GetLeft(), min);
230 EXPECT_EQ(rect.GetTop(), 10.0f);
231 EXPECT_EQ(rect.GetRight(), -inf);
232 EXPECT_EQ(rect.GetBottom(), 25.0f);
233 EXPECT_EQ(rect.GetX(), min);
234 EXPECT_EQ(rect.GetY(), 10.0f);
235 EXPECT_EQ(rect.GetWidth(), -inf);
236 EXPECT_EQ(rect.GetHeight(), 15.0f);
237 EXPECT_TRUE(rect.IsEmpty());
238 EXPECT_FALSE(rect.IsFinite());
239 }
240
241 {
242 Rect rect = Rect::MakeXYWH(5.0f, 10.0f, 20.0f, min);
243
244 EXPECT_EQ(rect.GetLeft(), 5.0f);
245 EXPECT_EQ(rect.GetTop(), 10.0f);
246 EXPECT_EQ(rect.GetRight(), 25.0f);
247 EXPECT_EQ(rect.GetBottom(), min);
248 EXPECT_EQ(rect.GetX(), 5.0f);
249 EXPECT_EQ(rect.GetY(), 10.0f);
250 EXPECT_EQ(rect.GetWidth(), 20.0f);
251 EXPECT_EQ(rect.GetHeight(), min);
252 EXPECT_TRUE(rect.IsEmpty());
253 EXPECT_TRUE(rect.IsFinite());
254 }
255
256 {
257 Rect rect = Rect::MakeXYWH(5.0f, min, 20.0f, min);
258
259 EXPECT_EQ(rect.GetLeft(), 5.0f);
260 EXPECT_EQ(rect.GetTop(), min);
261 EXPECT_EQ(rect.GetRight(), 25.0f);
262 EXPECT_EQ(rect.GetBottom(), -inf);
263 EXPECT_EQ(rect.GetX(), 5.0f);
264 EXPECT_EQ(rect.GetY(), min);
265 EXPECT_EQ(rect.GetWidth(), 20.0f);
266 EXPECT_EQ(rect.GetHeight(), -inf);
267 EXPECT_TRUE(rect.IsEmpty());
268 EXPECT_FALSE(rect.IsFinite());
269 }
270 }

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

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

Definition at line 2826 of file rect_unittests.cc.

2826 {
2827 {
2828 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
2829 auto actual = r.Project(r);
2830 auto expected = Rect::MakeLTRB(0, 0, 1, 1);
2831 EXPECT_RECT_NEAR(expected, actual);
2832 }
2833 {
2834 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
2835 auto actual = r.Project(Rect::MakeLTRB(0, 0, 100, 100));
2836 auto expected = Rect::MakeLTRB(0.5, 0.5, 1, 1);
2837 EXPECT_RECT_NEAR(expected, actual);
2838 }
2839 }

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

## ◆ TEST() [301/370]

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

Definition at line 2841 of file rect_unittests.cc.

2841 {
2842 {
2843 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
2844 EXPECT_EQ(Rect::RoundOut(r), r);
2845 }
2846 {
2847 auto r = Rect::MakeLTRB(-100.1, -100.1, 100.1, 100.1);
2848 EXPECT_EQ(Rect::RoundOut(r), Rect::MakeLTRB(-101, -101, 101, 101));
2849 }
2850 }

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

## ◆ TEST() [302/370]

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

Definition at line 709 of file rect_unittests.cc.

709 {
710 Rect rect;
711
712 EXPECT_EQ(Rect::RoundOut(rect), Rect());
713
714 EXPECT_EQ(IRect::RoundOut(rect), IRect());
715 }

References impeller::TRect< Scalar >::RoundOut(), and impeller::TRect< int64_t >::RoundOut().

## ◆ TEST() [303/370]

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

Definition at line 717 of file rect_unittests.cc.

717 {
718 Rect rect = Rect::MakeLTRB(5.125f, 10.75f, 20.625f, 25.375f);
719
720 EXPECT_EQ(Rect::RoundOut(rect), Rect::MakeLTRB(5.0f, 10.0f, 21.0f, 26.0f));
721
722 EXPECT_EQ(IRect::RoundOut(rect), IRect::MakeLTRB(5, 10, 21, 26));
723 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< int64_t >::MakeLTRB(), impeller::TRect< int64_t >::RoundOut(), and impeller::TRect< Scalar >::RoundOut().

## ◆ TEST() [304/370]

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

Definition at line 725 of file rect_unittests.cc.

725 {
726 auto test = [](int corners) {
727 EXPECT_TRUE(corners >= 0 && corners <= 0xf);
728 Scalar l, t, r, b;
729 int64_t il, it, ir, ib;
730 l = il = 50;
731 t = it = 50;
732 r = ir = 80;
733 b = ib = 80;
734 if ((corners & (1 << 0)) != 0) {
735 l = -1E20;
736 il = std::numeric_limits<int64_t>::min();
737 }
738 if ((corners & (1 << 1)) != 0) {
739 t = -1E20;
740 it = std::numeric_limits<int64_t>::min();
741 }
742 if ((corners & (1 << 2)) != 0) {
743 r = +1E20;
744 ir = std::numeric_limits<int64_t>::max();
745 }
746 if ((corners & (1 << 3)) != 0) {
747 b = +1E20;
748 ib = std::numeric_limits<int64_t>::max();
749 }
750
751 Rect rect = Rect::MakeLTRB(l, t, r, b);
752 IRect irect = IRect::RoundOut(rect);
753 EXPECT_EQ(irect.GetLeft(), il) << corners;
754 EXPECT_EQ(irect.GetTop(), it) << corners;
755 EXPECT_EQ(irect.GetRight(), ir) << corners;
756 EXPECT_EQ(irect.GetBottom(), ib) << corners;
757 };
758
759 for (int corners = 0; corners <= 15; corners++) {
760 test(corners);
761 }
762 }

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< int64_t >::RoundOut().

## ◆ TEST() [305/370]

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

Definition at line 884 of file rect_unittests.cc.

884 {
885 auto test1 = [](Rect rect, Scalar scale) {
886 Rect expected = Rect::MakeXYWH(rect.GetX() * scale, //
887 rect.GetY() * scale, //
888 rect.GetWidth() * scale, //
889 rect.GetHeight() * scale);
890
891 EXPECT_RECT_NEAR(rect.Scale(scale), expected) //
892 << rect << " * " << scale;
893 EXPECT_RECT_NEAR(rect.Scale(scale, scale), expected) //
894 << rect << " * " << scale;
895 EXPECT_RECT_NEAR(rect.Scale(Point(scale, scale)), expected) //
896 << rect << " * " << scale;
897 EXPECT_RECT_NEAR(rect.Scale(Size(scale, scale)), expected) //
898 << rect << " * " << scale;
899 };
900
901 auto test2 = [&test1](Rect rect, Scalar scale_x, Scalar scale_y) {
902 Rect expected = Rect::MakeXYWH(rect.GetX() * scale_x, //
903 rect.GetY() * scale_y, //
904 rect.GetWidth() * scale_x, //
905 rect.GetHeight() * scale_y);
906
907 EXPECT_RECT_NEAR(rect.Scale(scale_x, scale_y), expected) //
908 << rect << " * " << scale_x << ", " << scale_y;
909 EXPECT_RECT_NEAR(rect.Scale(Point(scale_x, scale_y)), expected) //
910 << rect << " * " << scale_x << ", " << scale_y;
911 EXPECT_RECT_NEAR(rect.Scale(Size(scale_x, scale_y)), expected) //
912 << rect << " * " << scale_x << ", " << scale_y;
913
914 test1(rect, scale_x);
915 test1(rect, scale_y);
916 };
917
918 test2(Rect::MakeLTRB(10, 15, 100, 150), 1.0, 0.0);
919 test2(Rect::MakeLTRB(10, 15, 100, 150), 0.0, 1.0);
920 test2(Rect::MakeLTRB(10, 15, 100, 150), 0.0, 0.0);
921 test2(Rect::MakeLTRB(10, 15, 100, 150), 2.5, 3.5);
922 test2(Rect::MakeLTRB(10, 15, 100, 150), 3.5, 2.5);
923 test2(Rect::MakeLTRB(10, 15, -100, 150), 2.5, 3.5);
924 test2(Rect::MakeLTRB(10, 15, 100, -150), 2.5, 3.5);
925 test2(Rect::MakeLTRB(10, 15, 100, 150), -2.5, 3.5);
926 test2(Rect::MakeLTRB(10, 15, 100, 150), 2.5, -3.5);
927 }

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

## ◆ TEST() [306/370]

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

Definition at line 2765 of file rect_unittests.cc.

2765 {
2766 auto r = Rect::MakeLTRB(0, 0, 100, 100);
2767
2768 EXPECT_EQ(r.Shift(Point(10, 5)), Rect::MakeLTRB(10, 5, 110, 105));
2769 EXPECT_EQ(r.Shift(Point(-10, -5)), Rect::MakeLTRB(-10, -5, 90, 95));
2770 }

References impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [307/370]

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

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

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

Definition at line 1313 of file rect_unittests.cc.

1313 {
1314 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1315 ASSERT_TRUE(a.IsFinite()) << label;
1316 ASSERT_TRUE(b.IsFinite()) << label;
1317 ASSERT_FALSE(a.Union(b).IsEmpty());
1318
1319 for (int i = 1; i < 16; i++) {
1320 // NaN in a produces b
1321 EXPECT_EQ(swap_nan(a, i).Union(b), b) << label << ", index = " << i;
1322 // NaN in b produces a
1323 EXPECT_EQ(a.Union(swap_nan(b, i)), a) << label << ", index = " << i;
1324 // NaN in both is empty
1325 for (int j = 1; j < 16; j++) {
1326 EXPECT_TRUE(swap_nan(a, i).Union(swap_nan(b, j)).IsEmpty())
1327 << label << ", indices = " << i << ", " << j;
1328 }
1329 }
1330 };
1331
1332 auto check_empty_flips = [](const Rect& a, const Rect& b,
1333 const std::string& label) {
1334 ASSERT_FALSE(a.IsEmpty());
1335 // b is allowed to be empty
1336
1337 // unflipped a vs flipped (empty) b yields a
1338 EXPECT_EQ(a.Union(flip_lr(b)), a) << label;
1339 EXPECT_EQ(a.Union(flip_tb(b)), a) << label;
1340 EXPECT_EQ(a.Union(flip_lrtb(b)), a) << label;
1341
1342 // flipped (empty) a vs unflipped b yields b
1343 EXPECT_EQ(flip_lr(a).Union(b), b) << label;
1344 EXPECT_EQ(flip_tb(a).Union(b), b) << label;
1345 EXPECT_EQ(flip_lrtb(a).Union(b), b) << label;
1346
1347 // flipped (empty) a vs flipped (empty) b yields empty
1348 EXPECT_TRUE(flip_lr(a).Union(flip_lr(b)).IsEmpty()) << label;
1349 EXPECT_TRUE(flip_tb(a).Union(flip_tb(b)).IsEmpty()) << label;
1350 EXPECT_TRUE(flip_lrtb(a).Union(flip_lrtb(b)).IsEmpty()) << label;
1351 };
1352
1353 auto test = [&check_nans, &check_empty_flips](const Rect& a, const Rect& b,
1354 const Rect& result) {
1355 ASSERT_FALSE(a.IsEmpty()) << a;
1356 // b is allowed to be empty
1357
1358 std::stringstream stream;
1359 stream << a << " union " << b;
1360 auto label = stream.str();
1361
1362 EXPECT_EQ(a.Union(b), result) << label;
1363 EXPECT_EQ(b.Union(a), result) << label;
1364 check_empty_flips(a, b, label);
1365 check_nans(a, b, label);
1366 };
1367
1368 {
1369 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1370 auto b = Rect::MakeXYWH(0, 0, 0, 0);
1371 auto expected = Rect::MakeXYWH(100, 100, 100, 100);
1372 test(a, b, expected);
1373 }
1374
1375 {
1376 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1377 auto b = Rect::MakeXYWH(0, 0, 1, 1);
1378 auto expected = Rect::MakeXYWH(0, 0, 200, 200);
1379 test(a, b, expected);
1380 }
1381
1382 {
1383 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1384 auto b = Rect::MakeXYWH(10, 10, 1, 1);
1385 auto expected = Rect::MakeXYWH(10, 10, 190, 190);
1386 test(a, b, expected);
1387 }
1388
1389 {
1390 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1391 auto b = Rect::MakeXYWH(10, 10, 100, 100);
1392 auto expected = Rect::MakeXYWH(0, 0, 110, 110);
1393 test(a, b, expected);
1394 }
1395
1396 {
1397 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1398 auto b = Rect::MakeXYWH(100, 100, 100, 100);
1399 auto expected = Rect::MakeXYWH(0, 0, 200, 200);
1400 test(a, b, expected);
1401 }
1402 }

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

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

Definition at line 1127 of file rect_unittests.cc.

1127 {
1128 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
1129
1130 // Non-empty
1131 EXPECT_FALSE(Rect::MakeXYWH(1.5, 2.3, 10.5, 7.2).IsEmpty());
1132
1133 // Empty both width and height both 0 or negative, in all combinations
1134 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 0.0).IsEmpty());
1135 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, -1.0).IsEmpty());
1136 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, -1.0).IsEmpty());
1137 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 0.0).IsEmpty());
1138
1139 // Empty for 0 or negative width or height (but not both at the same time)
1140 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, 0.0).IsEmpty());
1141 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, -1.0).IsEmpty());
1142 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 7.2).IsEmpty());
1143 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 7.2).IsEmpty());
1144
1145 // Empty for NaN in width or height or both
1146 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, nan).IsEmpty());
1147 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, 7.2).IsEmpty());
1148 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, nan).IsEmpty());
1149 }

References impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [311/370]

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | CreatesMSAAResolveWithCorrectStore |
| ) |  |

Definition at line 102 of file render_pass_builder_vk_unittests.cc.

102 {
103 RenderPassBuilderVK builder = RenderPassBuilderVK();
104 auto const context = MockVulkanContextBuilder().Build();
105
106 // Create an MSAA color attachment.
107 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
108 SampleCount::kCount4, LoadAction::kClear,
109 StoreAction::kMultisampleResolve);
110
111 auto render_pass = builder.Build(context->GetDevice());
112
113 EXPECT_TRUE(!!render_pass);
114
115 auto maybe_color = builder.GetColorAttachments().find(0u);
116 ASSERT_NE(maybe_color, builder.GetColorAttachments().end());
117 auto color = maybe_color->second;
118
119 // MSAA Texture.
120 EXPECT_EQ(color.initialLayout, vk::ImageLayout::eGeneral);
121 EXPECT_EQ(color.finalLayout, vk::ImageLayout::eGeneral);
122 EXPECT_EQ(color.loadOp, vk::AttachmentLoadOp::eClear);
123 EXPECT_EQ(color.storeOp, vk::AttachmentStoreOp::eDontCare);
124
125 auto maybe_resolve = builder.GetResolves().find(0u);
126 ASSERT_NE(maybe_resolve, builder.GetResolves().end());
127 auto resolve = maybe_resolve->second;
128
129 // MSAA Resolve Texture.
130 EXPECT_EQ(resolve.initialLayout, vk::ImageLayout::eGeneral);
131 EXPECT_EQ(resolve.finalLayout, vk::ImageLayout::eGeneral);
132 EXPECT_EQ(resolve.loadOp, vk::AttachmentLoadOp::eClear);
133 EXPECT_EQ(resolve.storeOp, vk::AttachmentStoreOp::eStore);
134 }

References impeller::RenderPassBuilderVK::Build(), impeller::RenderPassBuilderVK::GetColorAttachments(), impeller::RenderPassBuilderVK::GetResolves(), impeller::kClear, impeller::kCount4, impeller::kMultisampleResolve, impeller::kR8G8B8A8UNormInt, and impeller::RenderPassBuilderVK::SetColorAttachment().

## ◆ TEST() [312/370]

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | CreatesRenderPassWithCombinedDepthStencil |
| ) |  |

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 // Create a single color attachment with a transient depth stencil.
35 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
36 SampleCount::kCount1, LoadAction::kClear,
37 StoreAction::kStore);
38 builder.SetDepthStencilAttachment(PixelFormat::kD24UnormS8Uint,
39 SampleCount::kCount1, LoadAction::kDontCare,
40 StoreAction::kDontCare);
41
42 auto render_pass = builder.Build(context->GetDevice());
43
44 EXPECT_TRUE(!!render_pass);
45
46 auto maybe_color = builder.GetColorAttachments().find(0u);
47 ASSERT_NE(maybe_color, builder.GetColorAttachments().end());
48 auto color = maybe_color->second;
49
50 EXPECT_EQ(color.initialLayout, vk::ImageLayout::eGeneral);
51 EXPECT_EQ(color.finalLayout, vk::ImageLayout::eGeneral);
52 EXPECT_EQ(color.loadOp, vk::AttachmentLoadOp::eClear);
53 EXPECT_EQ(color.storeOp, vk::AttachmentStoreOp::eStore);
54
55 auto maybe_depth_stencil = builder.GetDepthStencil();
56 ASSERT_TRUE(maybe_depth_stencil.has_value());
57 if (!maybe_depth_stencil.has_value()) {
58 return;
59 }
60 auto depth_stencil = maybe_depth_stencil.value();
61
62 EXPECT_EQ(depth_stencil.initialLayout, vk::ImageLayout::eUndefined);
63 EXPECT_EQ(depth_stencil.finalLayout,
64 vk::ImageLayout::eDepthStencilAttachmentOptimal);
65 EXPECT_EQ(depth_stencil.loadOp, vk::AttachmentLoadOp::eDontCare);
66 EXPECT_EQ(depth_stencil.storeOp, vk::AttachmentStoreOp::eDontCare);
67 EXPECT_EQ(depth_stencil.stencilLoadOp, vk::AttachmentLoadOp::eDontCare);
68 EXPECT_EQ(depth_stencil.stencilStoreOp, vk::AttachmentStoreOp::eDontCare);
69 }

References impeller::RenderPassBuilderVK::Build(), impeller::RenderPassBuilderVK::GetColorAttachments(), impeller::RenderPassBuilderVK::GetDepthStencil(), impeller::kClear, impeller::kCount1, impeller::kD24UnormS8Uint, impeller::kDontCare, impeller::kR8G8B8A8UNormInt, impeller::kStore, impeller::RenderPassBuilderVK::SetColorAttachment(), and impeller::RenderPassBuilderVK::SetDepthStencilAttachment().

## ◆ TEST() [313/370]

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

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | CreatesRenderPassWithOnlyStencil |
| ) |  |

Definition at line 71 of file render_pass_builder_vk_unittests.cc.

71 {
72 RenderPassBuilderVK builder = RenderPassBuilderVK();
73 auto const context = MockVulkanContextBuilder().Build();
74
75 // Create a single color attachment with a transient depth stencil.
76 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
77 SampleCount::kCount1, LoadAction::kClear,
78 StoreAction::kStore);
79 builder.SetStencilAttachment(PixelFormat::kS8UInt, SampleCount::kCount1,
80 LoadAction::kDontCare, StoreAction::kDontCare);
81
82 auto render_pass = builder.Build(context->GetDevice());
83
84 EXPECT_TRUE(!!render_pass);
85
86 auto maybe_depth_stencil = builder.GetDepthStencil();
87 ASSERT_TRUE(maybe_depth_stencil.has_value());
88 if (!maybe_depth_stencil.has_value()) {
89 return;
90 }
91 auto depth_stencil = maybe_depth_stencil.value();
92
93 EXPECT_EQ(depth_stencil.initialLayout, vk::ImageLayout::eUndefined);
94 EXPECT_EQ(depth_stencil.finalLayout,
95 vk::ImageLayout::eDepthStencilAttachmentOptimal);
96 EXPECT_EQ(depth_stencil.loadOp, vk::AttachmentLoadOp::eDontCare);
97 EXPECT_EQ(depth_stencil.storeOp, vk::AttachmentStoreOp::eDontCare);
98 EXPECT_EQ(depth_stencil.stencilLoadOp, vk::AttachmentLoadOp::eDontCare);
99 EXPECT_EQ(depth_stencil.stencilStoreOp, vk::AttachmentStoreOp::eDontCare);
100 }

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

impeller::testing::TEST | ( | ResourceManagerVKTest | ,
|  | CreatesANewInstance |
| ) |  |

Definition at line 17 of file resource_manager_vk_unittests.cc.

17 {
18 auto const a = ResourceManagerVK::Create();
19 auto const b = ResourceManagerVK::Create();
20 EXPECT_NE(a, b);
21 }

References impeller::saturated::b, and impeller::ResourceManagerVK::Create().

## ◆ TEST() [316/370]

impeller::testing::TEST | ( | ResourceManagerVKTest | ,
|  | IsThreadSafe |
| ) |  |

Definition at line 77 of file resource_manager_vk_unittests.cc.

77 {
78 // In a typical app, there is a single ResourceManagerVK per app, shared b/w
79 // threads.
80 //
81 // This test ensures that the ResourceManagerVK is thread-safe.
82 std::weak_ptr<ResourceManagerVK> manager;
83
84 {
85 auto const manager = ResourceManagerVK::Create();
86
87 // Spawn two threads, and have them both put resources into the manager.
88 struct MockResource {};
89
90 std::thread thread1([&manager]() {
91 UniqueResourceVKT<MockResource>(manager, MockResource{});
92 });
93
94 std::thread thread2([&manager]() {
95 UniqueResourceVKT<MockResource>(manager, MockResource{});
96 });
97
98 thread1.join();
99 thread2.join();
100 }
101
102 // The thread should have terminated.
103 EXPECT_EQ(manager.lock(), nullptr);
104 }

References impeller::ResourceManagerVK::Create().

## ◆ TEST() [317/370]

impeller::testing::TEST | ( | ResourceManagerVKTest | ,
|  | ReclaimMovesAResourceAndDestroysIt |
| ) |  |

Definition at line 44 of file resource_manager_vk_unittests.cc.

44 {
45 auto const manager = ResourceManagerVK::Create();
46
47 auto waiter = fml::AutoResetWaitableEvent();
48 auto dead = false;
49 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
50
51 // Not killed immediately.
52 EXPECT_FALSE(waiter.IsSignaledForTest());
53
54 {
55 auto resource = UniqueResourceVKT<DeathRattle>(manager, std::move(rattle));
56 }
57
58 waiter.Wait();
59 }

References impeller::ResourceManagerVK::Create().

## ◆ TEST() [318/370]

impeller::testing::TEST | ( | ResourceManagerVKTest | ,
|  | TerminatesWhenOutOfScope |
| ) |  |

Definition at line 62 of file resource_manager_vk_unittests.cc.

62 {
63 // Originally, this shared_ptr was never destroyed, and the thread never
64 // terminated. This test ensures that the thread terminates when the
65 // ResourceManagerVK is out of scope.
66 std::weak_ptr<ResourceManagerVK> manager;
67
68 {
69 auto shared = ResourceManagerVK::Create();
70 manager = shared;
71 }
72
73 // The thread should have terminated.
74 EXPECT_EQ(manager.lock(), nullptr);
75 }

References impeller::ResourceManagerVK::Create().

## ◆ TEST() [319/370]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 84 of file shader_archive_unittests.cc.

84 {
85 // The unarchiving process depends on these identifiers to check to see if its
86 // a standalone archive or a multi-archive. Things will get nutty if these are
87 // ever the same.
88 auto archive_id = fb::ShaderArchiveIdentifier();
89 auto multi_archive_id = fb::MultiArchShaderArchiveIdentifier();
90 ASSERT_EQ(std::strlen(archive_id), std::strlen(multi_archive_id));
91 ASSERT_NE(std::strncmp(archive_id, multi_archive_id, std::strlen(archive_id)),
92 0);
93 }

## ◆ TEST() [338/370]

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

Definition at line 33 of file shader_archive_unittests.cc.

33 {
34 ShaderArchiveWriter writer;
35 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kVertex, "Hello",
36 CreateMappingFromString("World")));
37 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kFragment, "Foo",
38 CreateMappingFromString("Bar")));
39 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kVertex, "Baz",
40 CreateMappingFromString("Bang")));
41 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kVertex, "Ping",
42 CreateMappingFromString("Pong")));
43 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kFragment, "Pang",
44 CreateMappingFromString("World")));
45
46 auto mapping = writer.CreateMapping();
47 ASSERT_NE(mapping, nullptr);
48
49 MultiArchShaderArchiveWriter multi_writer;
50
51 ASSERT_TRUE(multi_writer.RegisterShaderArchive(
52 ArchiveRenderingBackend::kOpenGLES, mapping));
53
54 {
55 ScopedValidationDisable no_val;
56 // Can't add the same backend again.
57 ASSERT_FALSE(multi_writer.RegisterShaderArchive(
58 ArchiveRenderingBackend::kOpenGLES, mapping));
59 }
60
61 auto multi_mapping = multi_writer.CreateMapping();
62 ASSERT_TRUE(multi_mapping);
63
64 {
65 ScopedValidationDisable no_val;
66 auto no_library = MultiArchShaderArchive::CreateArchiveFromMapping(
67 multi_mapping, ArchiveRenderingBackend::kVulkan);
68 ASSERT_EQ(no_library, nullptr);
69 }
70
71 auto library = MultiArchShaderArchive::CreateArchiveFromMapping(
72 multi_mapping, ArchiveRenderingBackend::kOpenGLES);
73 ASSERT_EQ(library->GetShaderCount(), 5u);
74
75 // Wrong type.
76 ASSERT_EQ(library->GetMapping(ArchiveShaderType::kFragment, "Hello"),
77 nullptr);
78
79 auto hello_vtx = library->GetMapping(ArchiveShaderType::kVertex, "Hello");
80 ASSERT_NE(hello_vtx, nullptr);
81 ASSERT_EQ(CreateStringFromMapping(*hello_vtx), "World");
82 }

References impeller::ShaderArchiveWriter::AddShader(), impeller::MultiArchShaderArchive::CreateArchiveFromMapping(), impeller::MultiArchShaderArchiveWriter::CreateMapping(), impeller::ShaderArchiveWriter::CreateMapping(), CreateMappingFromString(), CreateStringFromMapping(), impeller::kFragment, impeller::kOpenGLES, impeller::kVertex, impeller::kVulkan, and impeller::MultiArchShaderArchiveWriter::RegisterShaderArchive().

## ◆ TEST() [339/370]

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

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

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

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

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

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

Definition at line 150 of file skia_conversions_unittests.cc.

150 {
151 std::vector<flutter::DlColor> colors = {
152 flutter::DlColor::kBlue(), flutter::DlColor::kGreen(),
153 flutter::DlColor::kGreen(), flutter::DlColor::kRed()};
154 std::vector<float> stops = {0.0, 0.5, 0.4, 1.0};
155 const auto gradient =
156 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
157 SkPoint::Make(1.0, 1.0), //
158 4, //
159 colors.data(), //
160 stops.data(), //
161 flutter::DlTileMode::kClamp, //
162 nullptr //
163 );
164
165 std::vector<Color> converted_colors;
166 std::vector<Scalar> converted_stops;
167 skia_conversions::ConvertStops(gradient.get(), converted_colors,
168 converted_stops);
169
170 // Value is clamped to 0.5
171 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
172 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
173 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 0.5f));
174 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[3], 1.0f));
175 }

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

## ◆ TEST() [345/370]

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

Definition at line 72 of file skia_conversions_unittests.cc.

72 {
73 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
74 flutter::DlColor::kRed()};
75 std::vector<float> stops = {0.5, 1.0};
76 const auto gradient =
77 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
78 SkPoint::Make(1.0, 1.0), //
79 2, //
80 colors.data(), //
81 stops.data(), //
82 flutter::DlTileMode::kClamp, //
83 nullptr //
84 );
85
86 std::vector<Color> converted_colors;
87 std::vector<Scalar> converted_stops;
88 skia_conversions::ConvertStops(gradient.get(), converted_colors,
89 converted_stops);
90
91 // First color is inserted as blue.
92 ASSERT_TRUE(ScalarNearlyEqual(converted_colors[0].blue, 1.0f));
93 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
94 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
95 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
96 }

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

## ◆ TEST() [346/370]

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

Definition at line 98 of file skia_conversions_unittests.cc.

98 {
99 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
100 flutter::DlColor::kRed()};
101 std::vector<float> stops = {0.0, .5};
102 const auto gradient =
103 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
104 SkPoint::Make(1.0, 1.0), //
105 2, //
106 colors.data(), //
107 stops.data(), //
108 flutter::DlTileMode::kClamp, //
109 nullptr //
110 );
111
112 std::vector<Color> converted_colors;
113 std::vector<Scalar> converted_stops;
114 skia_conversions::ConvertStops(gradient.get(), converted_colors,
115 converted_stops);
116
117 // Last color is inserted as red.
118 ASSERT_TRUE(ScalarNearlyEqual(converted_colors[2].red, 1.0f));
119 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
120 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
121 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
122 }

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

## ◆ TEST() [347/370]

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

Definition at line 46 of file skia_conversions_unittests.cc.

46 {
47 // Typical gradient.
48 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
49 flutter::DlColor::kRed(),
50 flutter::DlColor::kGreen()};
51 std::vector<float> stops = {0.0, 0.5, 1.0};
52 const auto gradient =
53 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
54 SkPoint::Make(1.0, 1.0), //
55 3, //
56 colors.data(), //
57 stops.data(), //
58 flutter::DlTileMode::kClamp, //
59 nullptr //
60 );
61
62 std::vector<Color> converted_colors;
63 std::vector<Scalar> converted_stops;
64 skia_conversions::ConvertStops(gradient.get(), converted_colors,
65 converted_stops);
66
67 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
68 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
69 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
70 }

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

## ◆ TEST() [348/370]

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

Definition at line 124 of file skia_conversions_unittests.cc.

124 {
125 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
126 flutter::DlColor::kGreen(),
127 flutter::DlColor::kRed()};
128 std::vector<float> stops = {0.0, 100, 1.0};
129 const auto gradient =
130 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
131 SkPoint::Make(1.0, 1.0), //
132 3, //
133 colors.data(), //
134 stops.data(), //
135 flutter::DlTileMode::kClamp, //
136 nullptr //
137 );
138
139 std::vector<Color> converted_colors;
140 std::vector<Scalar> converted_stops;
141 skia_conversions::ConvertStops(gradient.get(), converted_colors,
142 converted_stops);
143
144 // Value is clamped to 1.0
145 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
146 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 1.0f));
147 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
148 }

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

## ◆ TEST() [349/370]

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

Definition at line 14 of file skia_conversions_unittests.cc.

14 {
15 for (int x = -100; x < 100; x += 4) {
16 for (int y = -100; y < 100; y += 4) {
17 EXPECT_EQ(skia_conversions::ToPoint(SkPoint::Make(x * 0.25f, y * 0.25f)),
18 Point(x * 0.25f, y * 0.25f));
19 }
20 }
21 }

References impeller::skia_conversions::ToPoint().

## ◆ TEST() [350/370]

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

Definition at line 23 of file skia_conversions_unittests.cc.

23 {
24 for (int x = -100; x < 100; x += 4) {
25 for (int y = -100; y < 100; y += 4) {
26 EXPECT_EQ(skia_conversions::ToSize(SkPoint::Make(x * 0.25f, y * 0.25f)),
27 Size(x * 0.25f, y * 0.25f));
28 }
29 }
30 }

References impeller::skia_conversions::ToSize().

## ◆ TEST() [351/370]

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

Definition at line 32 of file skia_conversions_unittests.cc.

32 {
33 // Create a color with alpha, red, green, and blue values that are all
34 // trivially divisible by 255 so that we can test the conversion results in
35 // correct scalar values.
36 // AARRGGBB
37 const flutter::DlColor color = flutter::DlColor(0x8040C020);
38 auto converted_color = skia_conversions::ToColor(color);
39
40 ASSERT_TRUE(ScalarNearlyEqual(converted_color.alpha, 0x80 * (1.0f / 255)));
41 ASSERT_TRUE(ScalarNearlyEqual(converted_color.red, 0x40 * (1.0f / 255)));
42 ASSERT_TRUE(ScalarNearlyEqual(converted_color.green, 0xC0 * (1.0f / 255)));
43 ASSERT_TRUE(ScalarNearlyEqual(converted_color.blue, 0x20 * (1.0f / 255)));
44 }

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

## ◆ TEST() [352/370]

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

Definition at line 86 of file base_unittests.cc.

86 {
87 ASSERT_EQ(SPrintF("%sx%d", "Hello", 12), "Hellox12");
88 ASSERT_EQ(SPrintF(""), "");
89 ASSERT_EQ(SPrintF("Hello"), "Hello");
90 ASSERT_EQ(SPrintF("%sx%.2f", "Hello", 12.122222), "Hellox12.12");
91 }

References impeller::SPrintF().

## ◆ TEST() [353/370]

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

Definition at line 497 of file tessellator_unittests.cc.

497 {
498 auto tessellator = std::make_shared<Tessellator>();
499 PathBuilder builder;
500 builder.AddLine({0, 0}, {100, 100});
501 auto path = builder.TakePath();
502
503 auto polyline = tessellator->CreateTempPolyline(path, 0.1);
504 EXPECT_DEBUG_DEATH(tessellator->CreateTempPolyline(path, 0.1),
505 "point_buffer_");
506 }

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

## ◆ TEST() [354/370]

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

Definition at line 133 of file tessellator_unittests.cc.

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

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

## ◆ TEST() [355/370]

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

Definition at line 483 of file tessellator_unittests.cc.

483 {
484 // This path is not technically empty (it has a size in one dimension),
485 // but is otherwise completely flat.
486 auto tessellator = std::make_shared<Tessellator>();
487 PathBuilder builder;
488 builder.MoveTo({0, 0});
489 builder.MoveTo({10, 10}, /*relative=*/true);
490
491 auto points = tessellator->TessellateConvex(builder.TakePath(), 3.0);
492
493 EXPECT_TRUE(points.empty());
494 }

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

## ◆ TEST() [356/370]

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

Definition at line 169 of file tessellator_unittests.cc.

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

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

## ◆ TEST() [357/370]

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

Definition at line 351 of file tessellator_unittests.cc.

351 {
352 auto tessellator = std::make_shared<Tessellator>();
353
354 auto test = [&tessellator](const Matrix& transform, const Rect& bounds) {
355 auto center = bounds.GetCenter();
356 auto half_size = bounds.GetSize() * 0.5f;
357
358 auto generator = tessellator->FilledEllipse(transform, bounds);
359 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
360
361 auto vertex_count = generator.GetVertexCount();
362 auto vertices = std::vector<Point>();
363 generator.GenerateVertices([&vertices](const Point& p) { //
364 vertices.push_back(p);
365 });
366 EXPECT_EQ(vertices.size(), vertex_count);
367 ASSERT_EQ(vertex_count % 4, 0u);
368
369 auto quadrant_count = vertex_count / 4;
370 for (size_t i = 0; i < quadrant_count; i++) {
371 double angle = kPiOver2 * i / (quadrant_count - 1);
372 double degrees = angle * 180.0 / kPi;
373 double rcos = cos(angle) * half_size.width;
374 double rsin = sin(angle) * half_size.height;
375 EXPECT_POINT_NEAR(vertices[i * 2],
376 Point(center.x - rcos, center.y + rsin))
377 << "vertex " << i << ", angle = " << degrees << ", " //
378 << "bounds = " << bounds << std::endl;
379 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
380 Point(center.x - rcos, center.y - rsin))
381 << "vertex " << i << ", angle = " << degrees << ", " //
382 << "bounds = " << bounds << std::endl;
383 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
384 Point(center.x + rcos, center.y - rsin))
385 << "vertex " << i << ", angle = " << degrees << ", " //
386 << "bounds = " << bounds << std::endl;
387 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
388 Point(center.x + rcos, center.y + rsin))
389 << "vertex " << i << ", angle = " << degrees << ", " //
390 << "bounds = " << bounds << std::endl;
391 }
392 };
393
394 // Square bounds should actually use the circle generator, but its
395 // results should match the same math as the ellipse generator.
396 test({}, Rect::MakeXYWH(0, 0, 2, 2));
397
398 test({}, Rect::MakeXYWH(0, 0, 2, 3));
399 test({}, Rect::MakeXYWH(0, 0, 3, 2));
400 test({}, Rect::MakeXYWH(5, 10, 2, 3));
401 test({}, Rect::MakeXYWH(16, 7, 3, 2));
402 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 3, 2));
403 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 2, 3));
404 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
405 Rect::MakeXYWH(5000, 10000, 3000, 2000));
406 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
407 Rect::MakeXYWH(5000, 10000, 2000, 3000));
408 }

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

## ◆ TEST() [358/370]

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

Definition at line 410 of file tessellator_unittests.cc.

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

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

## ◆ TEST() [359/370]

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

Definition at line 280 of file tessellator_unittests.cc.

280 {
281 auto tessellator = std::make_shared<Tessellator>();
282
283 auto test = [&tessellator](const Matrix& transform, const Point& p0,
284 const Point& p1, Scalar radius) {
285 auto generator = tessellator->RoundCapLine(transform, p0, p1, radius);
286 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
287
288 auto vertex_count = generator.GetVertexCount();
289 auto vertices = std::vector<Point>();
290 generator.GenerateVertices([&vertices](const Point& p) { //
291 vertices.push_back(p);
292 });
293 EXPECT_EQ(vertices.size(), vertex_count);
294 ASSERT_EQ(vertex_count % 4, 0u);
295
296 Point along = p1 - p0;
297 Scalar length = along.GetLength();
298 if (length > 0) {
299 along *= radius / length;
300 } else {
301 along = {radius, 0};
302 }
303 Point across = {-along.y, along.x};
304
305 auto quadrant_count = vertex_count / 4;
306 for (size_t i = 0; i < quadrant_count; i++) {
307 double angle = kPiOver2 * i / (quadrant_count - 1);
308 double degrees = angle * 180.0 / kPi;
309 Point relative_along = along * cos(angle);
310 Point relative_across = across * sin(angle);
311 EXPECT_POINT_NEAR(vertices[i * 2], //
312 p0 - relative_along + relative_across)
313 << "vertex " << i << ", angle = " << degrees << ", " //
314 << "line = " << p0 << " => " << p1 << ", " //
315 << "radius = " << radius << std::endl;
316 EXPECT_POINT_NEAR(vertices[i * 2 + 1], //
317 p0 - relative_along - relative_across)
318 << "vertex " << i << ", angle = " << degrees << ", " //
319 << "line = " << p0 << " => " << p1 << ", " //
320 << "radius = " << radius << std::endl;
321 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1], //
322 p1 + relative_along - relative_across)
323 << "vertex " << i << ", angle = " << degrees << ", " //
324 << "line = " << p0 << " => " << p1 << ", " //
325 << "radius = " << radius << std::endl;
326 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2], //
327 p1 + relative_along + relative_across)
328 << "vertex " << i << ", angle = " << degrees << ", " //
329 << "line = " << p0 << " => " << p1 << ", " //
330 << "radius = " << radius << std::endl;
331 }
332 };
333
334 // Empty line should actually use the circle generator, but its
335 // results should match the same math as the round cap generator.
336 test({}, {0, 0}, {0, 0}, 10);
337
338 test({}, {0, 0}, {10, 0}, 2);
339 test({}, {10, 0}, {0, 0}, 2);
340 test({}, {0, 0}, {10, 10}, 2);
341
342 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {0, 0}, {10, 0}, 2);
343 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {10, 0}, {0, 0}, 2);
344 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {0, 0}, {10, 10}, 2);
345
346 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {0, 0}, {10, 0}, 2);
347 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {10, 0}, {0, 0}, 2);
348 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {0, 0}, {10, 10}, 2);
349 }

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

## ◆ TEST() [360/370]

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

Definition at line 212 of file tessellator_unittests.cc.

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

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

## ◆ TEST() [361/370]

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

Definition at line 107 of file tessellator_unittests.cc.

107 {
108 {
109 Tessellator t;
110 // Sanity check simple rectangle.
111 auto pts = t.TessellateConvex(
112 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 10, 10)).TakePath(), 1.0);
113
114 std::vector<Point> expected = {{0, 0}, {10, 0}, {0, 10}, {10, 10}};
115 EXPECT_EQ(pts, expected);
116 }
117
118 {
119 Tessellator t;
120 auto pts = t.TessellateConvex(PathBuilder{}
121 .AddRect(Rect::MakeLTRB(0, 0, 10, 10))
122 .AddRect(Rect::MakeLTRB(20, 20, 30, 30))
123 .TakePath(),
124 1.0);
125
126 std::vector<Point> expected = {{0, 0}, {10, 0}, {0, 10}, {10, 10},
127 {10, 10}, {20, 20}, {20, 20}, {30, 20},
128 {20, 30}, {30, 30}};
129 EXPECT_EQ(pts, expected);
130 }
131 }

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

## ◆ TEST() [362/370]

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

Definition at line 16 of file tessellator_unittests.cc.

16 {
17 // Zero points.
18 {
19 Tessellator t;
20 auto path = PathBuilder{}.TakePath(FillType::kOdd);
21 Tessellator::Result result = t.Tessellate(
22 path, 1.0f,
23 [](const float* vertices, size_t vertices_count,
24 const uint16_t* indices, size_t indices_count) { return true; });
25
26 ASSERT_EQ(result, Tessellator::Result::kInputError);
27 }
28
29 // One point.
30 {
31 Tessellator t;
32 auto path = PathBuilder{}.LineTo({0, 0}).TakePath(FillType::kOdd);
33 Tessellator::Result result = t.Tessellate(
34 path, 1.0f,
35 [](const float* vertices, size_t vertices_count,
36 const uint16_t* indices, size_t indices_count) { return true; });
37
38 ASSERT_EQ(result, Tessellator::Result::kSuccess);
39 }
40
41 // Two points.
42 {
43 Tessellator t;
44 auto path = PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath(FillType::kOdd);
45 Tessellator::Result result = t.Tessellate(
46 path, 1.0f,
47 [](const float* vertices, size_t vertices_count,
48 const uint16_t* indices, size_t indices_count) { return true; });
49
50 ASSERT_EQ(result, Tessellator::Result::kSuccess);
51 }
52
53 // Many points.
54 {
55 Tessellator t;
56 PathBuilder builder;
57 for (int i = 0; i < 1000; i++) {
58 auto coord = i * 1.0f;
59 builder.AddLine({coord, coord}, {coord + 1, coord + 1});
60 }
61 auto path = builder.TakePath(FillType::kOdd);
62 Tessellator::Result result = t.Tessellate(
63 path, 1.0f,
64 [](const float* vertices, size_t vertices_count,
65 const uint16_t* indices, size_t indices_count) { return true; });
66
67 ASSERT_EQ(result, Tessellator::Result::kSuccess);
68 }
69
70 // Closure fails.
71 {
72 Tessellator t;
73 auto path = PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath(FillType::kOdd);
74 Tessellator::Result result = t.Tessellate(
75 path, 1.0f,
76 [](const float* vertices, size_t vertices_count,
77 const uint16_t* indices, size_t indices_count) { return false; });
78
79 ASSERT_EQ(result, Tessellator::Result::kInputError);
80 }
81
82 // More than uint16 points, odd fill mode.
83 {
84 Tessellator t;
85 PathBuilder builder = {};
86 for (auto i = 0; i < 1000; i++) {
87 builder.AddCircle(Point(i, i), 4);
88 }
89 auto path = builder.TakePath(FillType::kOdd);
90 bool no_indices = false;
91 size_t count = 0u;
92 Tessellator::Result result = t.Tessellate(
93 path, 1.0f,
94 [&no_indices, &count](const float* vertices, size_t vertices_count,
95 const uint16_t* indices, size_t indices_count) {
96 no_indices = indices == nullptr;
97 count = vertices_count;
98 return true;
99 });
100
101 ASSERT_TRUE(no_indices);
102 ASSERT_TRUE(count >= USHRT_MAX);
103 ASSERT_EQ(result, Tessellator::Result::kSuccess);
104 }
105 }

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

## ◆ TEST() [363/370]

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 }

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

## ◆ TEST() [364/370]

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

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

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 int b = f.a; // NOLINT(clang-analyzer-deadcode.DeadStores)
63 FML_ALLOW_UNUSED_LOCAL(b);
64 f.mtx.UnlockReader();
65 }

References impeller::saturated::b, and impeller::testing::RWFoo::mtx.

## ◆ TEST() [367/370]

impeller::testing::TEST | ( | ThreadTest | ,
|  | CanCreateRWMutexLock |
| ) |  |

Definition at line 67 of file base_unittests.cc.

67 {
68 RWFoo f = {};
69
70 // f.a = 100; <--- Static analysis error.
71 {
72 auto write_lock = WriterLock{f.mtx};
73 f.a = 100;
74 }
75
76 // int b = f.a; <--- Static analysis error.
77 {
78 auto read_lock = ReaderLock(f.mtx);
79 int b = f.a; // NOLINT(clang-analyzer-deadcode.DeadStores)
80 FML_ALLOW_UNUSED_LOCAL(b);
81 }
82
83 // f.mtx.UnlockReader(); <--- Static analysis error.
84 }

References impeller::saturated::b, and impeller::testing::RWFoo::mtx.

## ◆ TEST() [368/370]

impeller::testing::TEST | ( | TraceSerializer | ,
|  | Save |
| ) |  |

Definition at line 11 of file trace_serializer_unittests.cc.

11 {
12 CanvasRecorder<TraceSerializer> recorder;
13 std::ostringstream ss;
14 fml::LogMessage::CaptureNextLog(&ss);
15 recorder.Save();
16 ASSERT_TRUE(ss.str().size() > 0);
17 }

## ◆ TEST() [369/370]

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

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

impeller::testing::TEST_F | ( | GoldenTests | ,
|  | ConicalGradient |
| ) |  |

Definition at line 71 of file golden_tests.cc.

71 {
72 Canvas canvas;
73 Paint paint;
74
75 paint.color_source = ColorSource::MakeConicalGradient(
76 {125, 125}, 125, {Color(1.0, 0.0, 0.0, 1.0), Color(0.0, 0.0, 1.0, 1.0)},
77 {0, 1}, {180, 180}, 0, Entity::TileMode::kClamp, {});
78
79 paint.stroke_width = 0.0;
80 paint.style = Paint::Style::kFill;
81 canvas.DrawRect(Rect::MakeXYWH(10, 10, 250, 250), paint);
82 Picture picture = canvas.EndRecordingAsPicture();
83
84 auto aiks_context =
85 AiksContext(Screenshotter().GetPlayground().GetContext(), nullptr);
86 auto screenshot = Screenshotter().MakeScreenshot(aiks_context, picture);
87 ASSERT_TRUE(SaveScreenshot(std::move(screenshot)));
88 }

References impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::Paint::kFill, impeller::ColorSource::MakeConicalGradient(), impeller::testing::Screenshotter::MakeScreenshot(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Paint::stroke_width, and impeller::Paint::style.

## ◆ TEST_P() [1/419]

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

Definition at line 365 of file aiks_path_unittests.cc.

365 {
366 Canvas canvas;
367 canvas.Scale(GetContentScale());
368
369 Paint paint;
370 paint.color = Color::Red();
371 std::vector<Color> colors = {Color{1.0, 0.0, 0.0, 1.0},
372 Color{0.0, 0.0, 0.0, 1.0}};
373 std::vector<Scalar> stops = {0.0, 1.0};
374 paint.color_source = ColorSource::MakeSweepGradient(
375 {100, 100}, Degrees(45), Degrees(135), std::move(colors),
376 std::move(stops), Entity::TileMode::kMirror, {});
377 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
378 .style = FilterContents::BlurStyle::kNormal,
379 .sigma = Sigma(20),
380 };
381
382 PathBuilder builder;
383 builder.AddArc(Rect::MakeXYWH(10, 10, 100, 100), Degrees(0), Degrees(0),
384 false);
385 canvas.DrawPath(builder.TakePath(), paint);
386
387 // Check that this empty picture can be created without crashing.
388 canvas.EndRecordingAsPicture();
389 }

References impeller::PathBuilder::AddArc(), impeller::Paint::color, impeller::Paint::color_source, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kMirror, impeller::FilterContents::kNormal, impeller::ColorSource::MakeSweepGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Paint::mask_blur_descriptor, impeller::Color::Red(), impeller::Canvas::Scale(), impeller::Paint::MaskBlurDescriptor::style, and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [2/419]

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

Definition at line 520 of file aiks_unittests.cc.

520 {
521 Canvas canvas;
522 Paint paint;
523
524 paint.color = Color::Red();
525 canvas.DrawPaint(paint);
526
527 paint.blend_mode = BlendMode::kSourceOver;
528 canvas.SaveLayer(paint);
529
530 paint.color = Color::White();
531 canvas.DrawRect(Rect::MakeXYWH(100, 100, 400, 400), paint);
532
533 paint.blend_mode = BlendMode::kSource;
534 canvas.SaveLayer(paint);
535
536 paint.color = Color::Blue();
537 canvas.DrawRect(Rect::MakeXYWH(200, 200, 200, 200), paint);
538
539 canvas.Restore();
540 canvas.Restore();
541
542 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
543 }

References impeller::Paint::blend_mode, impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSource, impeller::kSourceOver, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::White().

## ◆ TEST_P() [3/419]

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

Definition at line 201 of file aiks_blur_unittests.cc.

201 {
202 Canvas canvas;
203 canvas.Scale(GetContentScale());
204 canvas.DrawPaint({});
205 Paint blur = {
206 .color = Color::Green(),
207 .mask_blur_descriptor =
208 Paint::MaskBlurDescriptor{
209 .style = FilterContents::BlurStyle::kNormal,
210 .sigma = Sigma(47.6),
211 },
212 };
213 canvas.DrawRect(Rect::MakeXYWH(300, 300, 200, 200), blur);
214 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
215 }

References impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kNormal, impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [4/419]

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

Definition at line 217 of file aiks_blur_unittests.cc.

217 {
218 Canvas canvas;
219 canvas.Scale(GetContentScale());
220
221 auto paint_lines = [&canvas](Scalar dx, Scalar dy, Paint paint) {
222 auto draw_line = [&canvas, &paint](Point a, Point b) {
223 canvas.DrawPath(PathBuilder{}.AddLine(a, b).TakePath(), paint);
224 };
225 paint.stroke_width = 5;
226 paint.style = Paint::Style::kStroke;
227 draw_line(Point(dx + 100, dy + 100), Point(dx + 200, dy + 200));
228 draw_line(Point(dx + 100, dy + 200), Point(dx + 200, dy + 100));
229 draw_line(Point(dx + 150, dy + 100), Point(dx + 200, dy + 150));
230 draw_line(Point(dx + 100, dy + 150), Point(dx + 150, dy + 200));
231 };
232
233 AiksContext renderer(GetContext(), nullptr);
234 Canvas recorder_canvas;
235 for (int x = 0; x < 5; ++x) {
236 for (int y = 0; y < 5; ++y) {
237 Rect rect = Rect::MakeXYWH(x * 20, y * 20, 20, 20);
238 Paint paint{.color =
239 ((x + y) & 1) == 0 ? Color::Yellow() : Color::Blue()};
240 recorder_canvas.DrawRect(rect, paint);
241 }
242 }
243 Picture picture = recorder_canvas.EndRecordingAsPicture();
244 std::shared_ptr<Texture> texture =
245 picture.ToImage(renderer, ISize{100, 100})->GetTexture();
246
247 ColorSource image_source = ColorSource::MakeImage(
248 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {}, {});
249 std::shared_ptr<ImageFilter> blur_filter = ImageFilter::MakeBlur(
250 Sigma(5), Sigma(5), FilterContents::BlurStyle::kNormal,
251 Entity::TileMode::kDecal);
252 canvas.DrawRect(Rect::MakeLTRB(0, 0, 300, 600),
253 Paint{.color = Color::DarkGreen()});
254 canvas.DrawRect(Rect::MakeLTRB(100, 100, 200, 200),
255 Paint{.color_source = image_source});
256 canvas.DrawRect(Rect::MakeLTRB(300, 0, 600, 600),
257 Paint{.color = Color::Red()});
258 canvas.DrawRect(
259 Rect::MakeLTRB(400, 100, 500, 200),
260 Paint{.color_source = image_source, .image_filter = blur_filter});
261 paint_lines(0, 300, Paint{.color_source = image_source});
262 paint_lines(300, 300,
263 Paint{.color_source = image_source, .image_filter = blur_filter});
264 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
265 }

References impeller::PathBuilder::AddLine(), impeller::saturated::b, impeller::Color::Blue(), impeller::Paint::color, impeller::Paint::color_source, impeller::Color::DarkGreen(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::Entity::kRepeat, impeller::Paint::kStroke, impeller::ImageFilter::MakeBlur(), impeller::ColorSource::MakeImage(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Scale(), impeller::PathBuilder::TakePath(), impeller::Picture::ToImage(), and impeller::Color::Yellow().

## ◆ TEST_P() [5/419]

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

Definition at line 136 of file aiks_path_unittests.cc.

136 {
137 Canvas canvas;
138
139 // Starting at (50, 50), draw lines from:
140 // 1. (50, height)
141 // 2. (width, height)
142 // 3. (width, 50)
143 PathBuilder builder;
144 builder.MoveTo({50, 50});
145 builder.LineTo({50, 100});
146 builder.LineTo({100, 100});
147 builder.LineTo({100, 50});
148
149 Paint paint;
150 paint.color = Color::Red();
151 paint.style = Paint::Style::kStroke;
152 paint.stroke_width = 10;
153
154 canvas.DrawPath(builder.TakePath(), paint);
155
156 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
157 }

References impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, impeller::PathBuilder::LineTo(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Paint::stroke_width, impeller::Paint::style, and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [6/419]

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

Definition at line 159 of file aiks_path_unittests.cc.

159 {
160 Canvas canvas;
161
162 // Draw a stroked path that is explicitly closed to verify
163 // It doesn't become a rectangle.
164 PathBuilder builder;
165 builder.MoveTo({50, 50});
166 builder.LineTo({520, 120});
167 builder.LineTo({300, 310});
168 builder.LineTo({100, 50});
169 builder.Close();
170
171 Paint paint;
172 paint.color = Color::Red();
173 paint.style = Paint::Style::kStroke;
174 paint.stroke_width = 10;
175
176 canvas.DrawPath(builder.TakePath(), paint);
177
178 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
179 }

References impeller::PathBuilder::Close(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, impeller::PathBuilder::LineTo(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Paint::stroke_width, impeller::Paint::style, and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [7/419]

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

Definition at line 345 of file aiks_path_unittests.cc.

345 {
346 PathBuilder builder = {};
347 for (auto i = 0; i < 10; i++) {
348 if (i % 2 == 0) {
349 builder.AddCircle(Point(100 + 50 * i, 100 + 50 * i), 100);
350 } else {
351 builder.MoveTo({100.f + 50.f * i - 100, 100.f + 50.f * i});
352 builder.LineTo({100.f + 50.f * i, 100.f + 50.f * i - 100});
353 builder.LineTo({100.f + 50.f * i - 100, 100.f + 50.f * i - 100});
354 builder.Close();
355 }
356 }
357 builder.SetConvexity(Convexity::kConvex);
358
359 Canvas canvas;
360 canvas.DrawPath(builder.TakePath(), {.color = Color::Red().WithAlpha(0.4)});
361
362 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
363 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::Close(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::kConvex, impeller::PathBuilder::LineTo(), impeller::PathBuilder::MoveTo(), impeller::PathBuilder::SetConvexity(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [8/419]

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

Definition at line 972 of file aiks_unittests.cc.

972 {
973 Canvas canvas;
974 canvas.Scale(Vector2(0.2, 0.2));
975 canvas.DrawPaint({.color = Color::MediumTurquoise()});
976 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
977 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::MediumTurquoise(), and impeller::Canvas::Scale().

## ◆ TEST_P() [9/419]

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

Definition at line 979 of file aiks_unittests.cc.

979 {
980 Canvas canvas;
981 canvas.Scale(Vector2(0.2, 0.2));
982 canvas.DrawPaint({.color = Color::MediumTurquoise()});
983 canvas.DrawPaint({.color = Color::Color::OrangeRed().WithAlpha(0.5)});
984 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
985 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::MediumTurquoise(), and impeller::Canvas::Scale().

## ◆ TEST_P() [10/419]

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

Definition at line 1057 of file aiks_unittests.cc.

1057 {
1058 auto modes = GetBlendModeSelection();
1059
1060 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1061 static Color background = Color::MediumTurquoise();
1062 static Color foreground = Color::Color::OrangeRed().WithAlpha(0.5);
1063 static int current_blend_index = 3;
1064
1065 if (AiksTest::ImGuiBegin("Controls", nullptr,
1066 ImGuiWindowFlags_AlwaysAutoResize)) {
1067 ImGui::ColorEdit4("Background", reinterpret_cast<float*>(&background));
1068 ImGui::ColorEdit4("Foreground", reinterpret_cast<float*>(&foreground));
1069 ImGui::ListBox("Blend mode", &current_blend_index,
1070 modes.blend_mode_names.data(),
1071 modes.blend_mode_names.size());
1072 ImGui::End();
1073 }
1074
1075 Canvas canvas;
1076 canvas.Scale(Vector2(0.2, 0.2));
1077 canvas.DrawPaint({.color = background});
1078 canvas.DrawPaint(
1079 {.color = foreground,
1080 .blend_mode = static_cast<BlendMode>(current_blend_index)});
1081 return canvas.EndRecordingAsPicture();
1082 };
1083 ASSERT_TRUE(OpenPlaygroundHere(callback));
1084 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), GetBlendModeSelection(), impeller::AiksPlayground::ImGuiBegin(), impeller::Color::MediumTurquoise(), impeller::Canvas::Scale(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [11/419]

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

Definition at line 987 of file aiks_unittests.cc.

987 {
988 Canvas canvas;
989 canvas.Scale(Vector2(0.2, 0.2));
990 canvas.DrawPaint({.color = Color::MediumTurquoise()});
991 canvas.DrawPaint({.color = Color::Color::OrangeRed().WithAlpha(0.5),
992 .blend_mode = BlendMode::kHue});
993 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
994 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kHue, impeller::Color::MediumTurquoise(), and impeller::Canvas::Scale().

## ◆ TEST_P() [12/419]

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

Definition at line 3381 of file aiks_unittests.cc.

3381 {
3382 // Avoiding `GetSecondsElapsed()` to reduce risk of golden flakiness.
3383 int time = 0;
3384 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
3385 Canvas canvas;
3386
3387 canvas.Save();
3388 {
3389 canvas.Translate({300, 300});
3390
3391 // 1. Draw/restore a clip before drawing the image, which will get drawn
3392 // to the depth buffer behind the image.
3393 canvas.Save();
3394 {
3395 canvas.DrawPaint({.color = Color::Green()});
3396 canvas.ClipRect(Rect::MakeLTRB(-180, -180, 180, 180),
3397 Entity::ClipOperation::kDifference);
3398 canvas.DrawPaint({.color = Color::Black()});
3399 }
3400 canvas.Restore(); // Restore rectangle difference clip.
3401
3402 canvas.Save();
3403 {
3404 // 2. Draw an oval clip that applies to the image, which will get drawn
3405 // in front of the image on the depth buffer.
3406 canvas.ClipOval(Rect::MakeLTRB(-200, -200, 200, 200));
3407
3408 // 3. Draw the rotating image with a perspective transform.
3409 canvas.Transform(
3410 Matrix(1.0, 0.0, 0.0, 0.0, //
3411 0.0, 1.0, 0.0, 0.0, //
3412 0.0, 0.0, 1.0, 0.003, //
3413 0.0, 0.0, 0.0, 1.0) * //
3414 Matrix::MakeRotationY({Radians{-1.0f + (time++ / 60.0f)}}));
3415 auto image =
3416 std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
3417 canvas.DrawImage(image, -Point(image->GetSize()) / 2, {});
3418 }
3419 canvas.Restore(); // Restore oval intersect clip.
3420
3421 // 4. Draw a semi-translucent blue circle atop all previous draws.
3422 canvas.DrawCircle({}, 230, {.color = Color::Blue().WithAlpha(0.4)});
3423 }
3424 canvas.Restore(); // Restore translation.
3425
3426 return canvas.EndRecordingAsPicture();
3427 };
3428 ASSERT_TRUE(OpenPlaygroundHere(callback));
3429 }

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Canvas::ClipOval(), impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawImage(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kDifference, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeRotationY(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::Transform(), impeller::Canvas::Translate(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [13/419]

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

Definition at line 2776 of file aiks_unittests.cc.

2776 {
2777 std::vector<Point> points = {
2778 {0, 0}, //
2779 {100, 100}, //
2780 {100, 0}, //
2781 {0, 100}, //
2782 {0, 0}, //
2783 {48, 48}, //
2784 {52, 52}, //
2785 };
2786 std::vector<PointStyle> caps = {
2787 PointStyle::kRound,
2788 PointStyle::kSquare,
2789 };
2790 Paint paint;
2791 paint.color = Color::Yellow().WithAlpha(0.5);
2792
2793 Paint background;
2794 background.color = Color::Black();
2795
2796 Canvas canvas;
2797 canvas.DrawPaint(background);
2798 canvas.Translate({200, 200});
2799 canvas.DrawPoints(points, 10, paint, PointStyle::kRound);
2800 canvas.Translate({150, 0});
2801 canvas.DrawPoints(points, 10, paint, PointStyle::kSquare);
2802
2803 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2804 }

References impeller::Color::Black(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPoints(), impeller::Canvas::EndRecordingAsPicture(), impeller::kRound, impeller::kSquare, impeller::Canvas::Translate(), impeller::Color::WithAlpha(), and impeller::Color::Yellow().

## ◆ TEST_P() [14/419]

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

Definition at line 2870 of file aiks_unittests.cc.

2870 {
2871 auto texture = CreateTextureForFixture("table_mountain_nx.png",
2872 /*enable_mipmapping=*/true);
2873
2874 std::vector<Point> points = {
2875 {0, 0}, //
2876 {100, 100}, //
2877 {100, 0}, //
2878 {0, 100}, //
2879 {0, 0}, //
2880 {48, 48}, //
2881 {52, 52}, //
2882 };
2883 std::vector<PointStyle> caps = {
2884 PointStyle::kRound,
2885 PointStyle::kSquare,
2886 };
2887 Paint paint;
2888 paint.color_source = ColorSource::MakeImage(texture, Entity::TileMode::kClamp,
2889 Entity::TileMode::kClamp, {}, {});
2890
2891 Canvas canvas;
2892 canvas.Translate({200, 200});
2893 canvas.DrawPoints(points, 100, paint, PointStyle::kRound);
2894 canvas.Translate({150, 0});
2895 canvas.DrawPoints(points, 100, paint, PointStyle::kSquare);
2896
2897 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2898 }

References impeller::Paint::color_source, impeller::Entity::kClamp, impeller::kRound, impeller::kSquare, impeller::ColorSource::MakeImage(), and impeller::Canvas::Translate().

## ◆ TEST_P() [15/419]

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

Definition at line 501 of file aiks_unittests.cc.

501 {
502 Canvas recorder_canvas;
503
504 Canvas canvas;
505 AiksContext renderer(GetContext(), nullptr);
506 Paint paint;
507 paint.color = Color::BlackTransparent();
508 canvas.DrawPaint(paint);
509 Picture picture = recorder_canvas.EndRecordingAsPicture();
510 auto image = picture.ToImage(renderer, ISize{1000, 1000});
511 if (image) {
512 canvas.DrawImage(image, Point(), Paint());
513 paint.color = Color{0.1, 0.1, 0.1, 0.2};
514 canvas.DrawRect(Rect::MakeSize(ISize{1000, 1000}), paint);
515 }
516
517 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
518 }

References impeller::Color::BlackTransparent(), impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeSize(), and impeller::Picture::ToImage().

## ◆ TEST_P() [16/419]

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

Definition at line 610 of file aiks_unittests.cc.

610 {
611 Canvas canvas;
612
613 Paint red;
614 red.color = Color::Red();
615
616 canvas.DrawCircle({250, 250}, 125, red);
617
618 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
619 }

References impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Color::Red().

## ◆ TEST_P() [17/419]

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

Definition at line 633 of file aiks_unittests.cc.

633 {
634 Canvas canvas;
635
636 Paint red;
637 red.color = Color::Red();
638
639 Paint green;
640 green.color = Color::Green();
641
642 Paint blue;
643 blue.color = Color::Blue();
644
645 Paint save;
646 save.color = Color::Black();
647
648 canvas.SaveLayer(save, Rect::MakeXYWH(0, 0, 50, 50));
649
650 canvas.DrawRect(Rect::MakeXYWH(0, 0, 100, 100), red);
651 canvas.DrawRect(Rect::MakeXYWH(10, 10, 100, 100), green);
652 canvas.DrawRect(Rect::MakeXYWH(20, 20, 100, 100), blue);
653
654 canvas.Restore();
655
656 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
657 }

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [18/419]

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

Definition at line 659 of file aiks_unittests.cc.

660 {
661 Canvas canvas;
662
663 Paint red;
664 red.color = Color::Red();
665
666 Paint green;
667 green.color = Color::Green();
668
669 Paint blue;
670 blue.color = Color::Blue();
671
672 Paint save;
673 save.color = Color::Black().WithAlpha(0.5);
674
675 canvas.SaveLayer(save, Rect::MakeXYWH(0, 0, 100000, 100000));
676
677 canvas.DrawRect(Rect::MakeXYWH(0, 0, 100, 100), red);
678 canvas.DrawRect(Rect::MakeXYWH(10, 10, 100, 100), green);
679 canvas.DrawRect(Rect::MakeXYWH(20, 20, 100, 100), blue);
680
681 canvas.Restore();
682
683 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
684 }

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [19/419]

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

Definition at line 621 of file aiks_unittests.cc.

621 {
622 Canvas canvas;
623
624 Paint red;
625 red.color = Color::Red();
626
627 canvas.Skew(2, 5);
628 canvas.DrawRect(Rect::MakeXYWH(0, 0, 100, 100), red);
629
630 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
631 }

References impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), and impeller::Canvas::Skew().

## ◆ TEST_P() [20/419]

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

Definition at line 475 of file aiks_unittests.cc.

475 {
476 Canvas recorder_canvas;
477 Paint paint;
478 paint.color = Color{0.9568, 0.2627, 0.2118, 1.0};
479 recorder_canvas.DrawRect(Rect::MakeXYWH(100.0, 100.0, 600, 600), paint);
480 paint.color = Color{0.1294, 0.5882, 0.9529, 1.0};
481 recorder_canvas.DrawRect(Rect::MakeXYWH(200.0, 200.0, 600, 600), paint);
482
483 Canvas canvas;
484 AiksContext renderer(GetContext(), nullptr);
485 paint.color = Color::BlackTransparent();
486 canvas.DrawPaint(paint);
487 Picture picture = recorder_canvas.EndRecordingAsPicture();
488 auto image = picture.ToImage(renderer, ISize{1000, 1000});
489 if (image) {
490 canvas.DrawImage(image, Point(), Paint());
491 paint.color = Color{0.1, 0.1, 0.1, 0.2};
492 canvas.DrawRect(Rect::MakeSize(ISize{1000, 1000}), paint);
493 }
494
495 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
496 }

References impeller::Color::BlackTransparent(), impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Picture::ToImage().

## ◆ TEST_P() [21/419]

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

Definition at line 133 of file aiks_unittests.cc.

133 {
134 Canvas canvas;
135
136 Rect layer_rect = Rect::MakeXYWH(0, 0, 500, 500);
137 canvas.ClipRect(layer_rect);
138
139 canvas.SaveLayer(
140 {
141 .color_filter = ColorFilter::MakeBlend(BlendMode::kDifference,
142 Color(0, 1, 0, 0.5)),
143 },
144 layer_rect);
145
146 Paint paint;
147 canvas.DrawPaint({.color = Color::Black()});
148 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300),
149 {.color = Color::White()});
150 canvas.Restore();
151
152 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
153 }

References impeller::Color::Black(), impeller::Canvas::ClipRect(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kDifference, impeller::ColorFilter::MakeBlend(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::White().

## ◆ TEST_P() [22/419]

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

Definition at line 102 of file aiks_blur_unittests.cc.

102 {
103 Canvas canvas;
104 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
105 canvas.DrawCircle({300, 200}, 100, {.color = Color::GreenYellow()});
106 canvas.DrawCircle({140, 170}, 75, {.color = Color::DarkMagenta()});
107 canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
108 canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), {20, 20});
109 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
110 ImageFilter::MakeBlur(Sigma(30.0), Sigma(30.0),
111 FilterContents::BlurStyle::kNormal,
112 Entity::TileMode::kClamp));
113 canvas.Restore();
114
115 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
116 }

References impeller::Canvas::ClipRRect(), impeller::Color::CornflowerBlue(), impeller::Color::DarkMagenta(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::GreenYellow(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Color::OrangeRed(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [23/419]

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

Definition at line 118 of file aiks_blur_unittests.cc.

118 {
119 Canvas canvas;
120 canvas.DrawCircle({400, 400}, 300, {.color = Color::Green()});
121 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
122 ImageFilter::MakeBlur(Sigma(999999), Sigma(999999),
123 FilterContents::BlurStyle::kNormal,
124 Entity::TileMode::kClamp));
125 canvas.Restore();
126
127 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
128 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::ImageFilter::MakeBlur(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [24/419]

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

Definition at line 78 of file aiks_blur_unittests.cc.

78 {
79 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
80 static PlaygroundPoint point_a(Point(50, 50), 30, Color::White());
81 static PlaygroundPoint point_b(Point(300, 200), 30, Color::White());
82 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
83
84 Canvas canvas;
85 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
86 canvas.DrawCircle({300, 200}, 100, {.color = Color::GreenYellow()});
87 canvas.DrawCircle({140, 170}, 75, {.color = Color::DarkMagenta()});
88 canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
89 canvas.ClipRRect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), {20, 20});
90 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
91 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
92 FilterContents::BlurStyle::kNormal,
93 Entity::TileMode::kClamp));
94 canvas.Restore();
95
96 return canvas.EndRecordingAsPicture();
97 };
98
99 ASSERT_TRUE(OpenPlaygroundHere(callback));
100 }

References impeller::saturated::b, impeller::Canvas::ClipRRect(), impeller::Color::CornflowerBlue(), impeller::Color::DarkMagenta(), impeller::Canvas::DrawCircle(), impeller::DrawPlaygroundLine(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::GreenYellow(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Color::OrangeRed(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::White().

## ◆ TEST_P() [25/419]

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

Definition at line 3431 of file aiks_unittests.cc.

3431 {
3432 Canvas canvas;
3433 Paint paint;
3434
3435 canvas.Scale(GetContentScale());
3436
3437 // Draw something interesting in the background.
3438 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
3439 Color{0.1294, 0.5882, 0.9529, 1.0}};
3440 std::vector<Scalar> stops = {
3441 0.0,
3442 1.0,
3443 };
3444 paint.color_source = ColorSource::MakeLinearGradient(
3445 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
3446 Entity::TileMode::kRepeat, {});
3447 canvas.DrawPaint(paint);
3448
3449 Rect clip_rect = Rect::MakeLTRB(50, 50, 400, 300);
3450
3451 // Draw a clipped SaveLayer, where the clip coverage and SaveLayer size are
3452 // the same.
3453 canvas.ClipRRect(clip_rect, Size(100, 100),
3454 Entity::ClipOperation::kIntersect);
3455 canvas.SaveLayer({}, clip_rect,
3456 ImageFilter::MakeFromColorFilter(*ColorFilter::MakeBlend(
3457 BlendMode::kExclusion, Color::Red())));
3458 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3459 }

References impeller::Canvas::ClipRRect(), impeller::Paint::color_source, impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kExclusion, impeller::Entity::kIntersect, impeller::Entity::kRepeat, impeller::ColorFilter::MakeBlend(), impeller::ImageFilter::MakeFromColorFilter(), impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Color::Red(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Scale().

## ◆ TEST_P() [26/419]

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

Definition at line 130 of file aiks_blur_unittests.cc.

130 {
131 Canvas canvas;
132 canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
133 canvas.DrawCircle(
134 {400, 400}, 200,
135 {
136 .color = Color::Green(),
137 .image_filter = ImageFilter::MakeBlur(
138 Sigma(20.0), Sigma(20.0), FilterContents::BlurStyle::kNormal,
139 Entity::TileMode::kDecal),
140 });
141 canvas.Restore();
142
143 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
144 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Canvas::Restore().

## ◆ TEST_P() [27/419]

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

Definition at line 1800 of file aiks_unittests.cc.

1800 {
1801 Canvas canvas;
1802
1803 canvas.DrawPaint({.color = Color::White()});
1804
1805 // Draw a green circle on the screen.
1806 {
1807 // Increase the clip depth for the savelayer to contend with.
1808 canvas.ClipPath(PathBuilder{}.AddCircle({100, 100}, 50).TakePath());
1809
1810 canvas.SaveLayer({}, Rect::MakeXYWH(50, 50, 100, 100));
1811
1812 // Fill the layer with white.
1813 canvas.DrawRect(Rect::MakeSize(Size{400, 400}), {.color = Color::White()});
1814 // Fill the layer with green, but do so with a color blend that can't be
1815 // collapsed into the parent pass.
1816 // TODO(jonahwilliams): this blend mode was changed from color burn to
1817 // hardlight to work around https://github.com/flutter/flutter/issues/136554
1818 // .
1819 canvas.DrawRect(
1820 Rect::MakeSize(Size{400, 400}),
1821 {.color = Color::Green(), .blend_mode = BlendMode::kHardLight});
1822 }
1823
1824 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1825 }

References impeller::PathBuilder::AddCircle(), impeller::Canvas::ClipPath(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::kHardLight, impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::SaveLayer(), and impeller::Color::White().

## ◆ TEST_P() [28/419]

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

Definition at line 2714 of file aiks_unittests.cc.

2714 {
2715 auto runtime_stages =
2716 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2717
2718 auto runtime_stage =
2719 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2720 ASSERT_TRUE(runtime_stage);
2721 ASSERT_TRUE(runtime_stage->IsDirty());
2722
2723 struct FragUniforms {
2724 Vector2 iResolution;
2725 Scalar iTime;
2726 } frag_uniforms = {.iResolution = Vector2(400, 400), .iTime = 100.0};
2727 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2728 uniform_data->resize(sizeof(FragUniforms));
2729 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2730
2731 std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
2732
2733 Paint paint;
2734 paint.color_source = ColorSource::MakeRuntimeEffect(
2735 runtime_stage, uniform_data, texture_inputs);
2736
2737 Canvas canvas;
2738 canvas.Save();
2739 canvas.ClipRRect(Rect::MakeXYWH(0, 0, 400, 400), {10.0, 10.0},
2740 Entity::ClipOperation::kIntersect);
2741 canvas.DrawRect(Rect::MakeXYWH(0, 0, 400, 400), paint);
2742 canvas.Restore();
2743
2744 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2745 }

References impeller::Canvas::ClipRRect(), impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kIntersect, impeller::ColorSource::MakeRuntimeEffect(), impeller::TRect< Scalar >::MakeXYWH(), impeller::PlaygroundBackendToRuntimeStageBackend(), impeller::Canvas::Restore(), and impeller::Canvas::Save().

## ◆ TEST_P() [29/419]

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

Definition at line 391 of file aiks_path_unittests.cc.

391 {
392 Canvas canvas;
393 Paint paint;
394 paint.color = Color::Fuchsia();
395 canvas.ClipPath(
396 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 500, 500)).TakePath());
397 canvas.DrawPath(PathBuilder{}.AddCircle({500, 500}, 250).TakePath(), paint);
398 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
399 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddRect(), impeller::Canvas::ClipPath(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Fuchsia(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [30/419]

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

Definition at line 76 of file aiks_unittests.cc.

76 {
77 Canvas canvas;
78 Paint paint;
79 paint.color = Color::Blue();
80 canvas.DrawPath(PathBuilder{}
81 .AddRect(Rect::MakeXYWH(100.0, 100.0, 100.0, 100.0))
82 .TakePath(),
83 paint);
84 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
85 }

References impeller::PathBuilder::AddRect(), impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [31/419]

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

Definition at line 109 of file aiks_unittests.cc.

109 {
110 Canvas canvas;
111 Paint paint;
112 paint.color = Color::Red();
113 paint.color_filter =
114 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow());
115 paint.invert_colors = true;
116
117 canvas.DrawRect(Rect::MakeLTRB(0, 0, 100, 100), paint);
118 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
119 }

References impeller::Paint::color, impeller::Paint::color_filter, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::invert_colors, impeller::kSourceOver, impeller::ColorFilter::MakeBlend(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Color::Red(), and impeller::Color::Yellow().

## ◆ TEST_P() [32/419]

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

Definition at line 121 of file aiks_unittests.cc.

121 {
122 Canvas canvas;
123 Paint paint;
124 paint.color = Color::Red();
125 paint.color_filter =
126 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow());
127 paint.invert_colors = true;
128
129 canvas.DrawPaint(paint);
130 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
131 }

References impeller::Paint::color, impeller::Paint::color_filter, impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::invert_colors, impeller::kSourceOver, impeller::ColorFilter::MakeBlend(), impeller::Color::Red(), and impeller::Color::Yellow().

## ◆ TEST_P() [33/419]

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

Definition at line 562 of file aiks_gradient_unittests.cc.

562 {
563 Scalar size = 256;
564 Canvas canvas;
565 Paint paint;
566 paint.color = Color::White();
567 canvas.DrawRect(Rect::MakeXYWH(0, 0, size * 3, size * 3), paint);
568 std::vector<Color> colors = {Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF),
569 Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF),
570 Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF),
571 Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF)};
572 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
573 std::array<std::tuple<Point, float, Point, float>, 8> array{
574 std::make_tuple(Point{size / 2.f, size / 2.f}, 0.f,
575 Point{size / 2.f, size / 2.f}, size / 2.f),
576 std::make_tuple(Point{size / 2.f, size / 2.f}, size / 4.f,
577 Point{size / 2.f, size / 2.f}, size / 2.f),
578 std::make_tuple(Point{size / 4.f, size / 4.f}, 0.f,
579 Point{size / 2.f, size / 2.f}, size / 2.f),
580 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 2.f,
581 Point{size / 2.f, size / 2.f}, 0),
582 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 4.f,
583 Point{size / 2.f, size / 2.f}, size / 2.f),
584 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 16.f,
585 Point{size / 2.f, size / 2.f}, size / 8.f),
586 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 8.f,
587 Point{size / 2.f, size / 2.f}, size / 16.f),
588 std::make_tuple(Point{size / 8.f, size / 8.f}, size / 8.f,
589 Point{size / 2.f, size / 2.f}, size / 8.f),
590 };
591 for (int i = 0; i < 8; i++) {
592 canvas.Save();
593 canvas.Translate({(i % 3) * size, i / 3 * size, 0});
594 paint.color_source = ColorSource::MakeConicalGradient(
595 std::get<0>(array[i]), std::get<1>(array[i]), colors, stops,
596 std::get<2>(array[i]), std::get<3>(array[i]), Entity::TileMode::kClamp,
597 {});
598 canvas.DrawRect(Rect::MakeXYWH(0, 0, size, size), paint);
599 canvas.Restore();
600 }
601 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
602 }

References impeller::Paint::color, impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::ColorSource::MakeConicalGradient(), impeller::Color::MakeRGBA8(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::Translate(), and impeller::Color::White().

## ◆ TEST_P() [34/419]

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

Definition at line 187 of file aiks_gradient_unittests.cc.

187 {
188 CanRenderConicalGradientWithDithering(this, false);
189 }

References CanRenderConicalGradientWithDithering().

## ◆ TEST_P() [35/419]

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

Definition at line 191 of file aiks_gradient_unittests.cc.

191 {
192 CanRenderConicalGradientWithDithering(this, true);
193 }

References CanRenderConicalGradientWithDithering().

## ◆ TEST_P() [36/419]

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

Definition at line 56 of file aiks_path_unittests.cc.

56 {
57 Canvas canvas;
58 Paint paint;
59 paint.color = Color::Red();
60 paint.stroke_width = 25.0;
61 paint.style = Paint::Style::kStroke;
62 canvas.DrawPath(PathBuilder{}.AddCircle({500, 500}, 250).TakePath(), paint);
63 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
64 }

References impeller::PathBuilder::AddCircle(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, impeller::Color::Red(), impeller::Paint::stroke_width, and impeller::Paint::style.

## ◆ TEST_P() [37/419]

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

Definition at line 2699 of file aiks_unittests.cc.

2699 {
2700 Canvas canvas;
2701
2702 canvas.DrawPaint({.color = Color::Red()});
2703 // Draw an empty savelayer with a destructive blend mode, which will replace
2704 // the entire red screen with fully transparent black, except for the green
2705 // circle drawn within the layer.
2706 canvas.SaveLayer({.blend_mode = BlendMode::kSource});
2707 canvas.DrawCircle({300, 300}, 100, {.color = Color::Green()});
2708 canvas.Restore();
2709
2710 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2711 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::kSource, impeller::Color::Red(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [38/419]

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

Definition at line 352 of file aiks_unittests.cc.

352 {
353 Paint paint;
354 Canvas canvas;
355 canvas.Translate({400, 400});
356
357 // Limit drawing to face circle with a clip.
358 canvas.ClipPath(PathBuilder{}.AddCircle(Point(), 200).TakePath());
359 canvas.Save();
360
361 // Cut away eyes/mouth using difference clips.
362 canvas.ClipPath(PathBuilder{}.AddCircle({-100, -50}, 30).TakePath(),
363 Entity::ClipOperation::kDifference);
364 canvas.ClipPath(PathBuilder{}.AddCircle({100, -50}, 30).TakePath(),
365 Entity::ClipOperation::kDifference);
366 canvas.ClipPath(PathBuilder{}
367 .AddQuadraticCurve({-100, 50}, {0, 150}, {100, 50})
368 .TakePath(),
369 Entity::ClipOperation::kDifference);
370
371 // Draw a huge yellow rectangle to prove the clipping works.
372 paint.color = Color::Yellow();
373 canvas.DrawRect(Rect::MakeXYWH(-1000, -1000, 2000, 2000), paint);
374
375 // Remove the difference clips and draw hair that partially covers the eyes.
376 canvas.Restore();
377 paint.color = Color::Maroon();
378 canvas.DrawPath(PathBuilder{}
379 .MoveTo({200, -200})
380 .HorizontalLineTo(-200)
381 .VerticalLineTo(-40)
382 .CubicCurveTo({0, -40}, {0, -80}, {200, -80})
383 .TakePath(),
384 paint);
385
386 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
387 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddQuadraticCurve(), impeller::Canvas::ClipPath(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kDifference, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Maroon(), impeller::PathBuilder::MoveTo(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::Translate(), and impeller::Color::Yellow().

## ◆ TEST_P() [39/419]

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

Definition at line 107 of file aiks_path_unittests.cc.

107 {
108 Canvas canvas;
109
110 Paint paint;
111 paint.color = Color::Red();
112
113 PathBuilder builder;
114
115 PathBuilder::RoundingRadii radii;
116 radii.top_left = {50, 25};
117 radii.top_right = {25, 50};
118 radii.bottom_right = {50, 25};
119 radii.bottom_left = {25, 50};
120
121 builder.AddRoundedRect(Rect::MakeXYWH(100, 100, 200, 200), radii);
122 builder.AddCircle({200, 200}, 50);
123 auto path = builder.TakePath(FillType::kOdd);
124
125 canvas.DrawImage(
126 std::make_shared<Image>(CreateTextureForFixture("boston.jpg")), {10, 10},
127 Paint{});
128 canvas.DrawPath(path, paint);
129
130 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
131 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddRoundedRect(), impeller::PathBuilder::RoundingRadii::bottom_left, impeller::PathBuilder::RoundingRadii::bottom_right, impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::kOdd, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::PathBuilder::TakePath(), impeller::PathBuilder::RoundingRadii::top_left, and impeller::PathBuilder::RoundingRadii::top_right.

## ◆ TEST_P() [40/419]

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

Definition at line 448 of file aiks_unittests.cc.

448 {
449 Canvas canvas;
450 Paint paint;
451
452 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
453 Color{0.1294, 0.5882, 0.9529, 1.0}};
454 std::vector<Scalar> stops = {
455 0.0,
456 1.0,
457 };
458
459 paint.color_source = ColorSource::MakeLinearGradient(
460 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
461 Entity::TileMode::kRepeat, {});
462
463 canvas.Save();
464 canvas.Translate({100, 100, 0});
465 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), paint);
466 canvas.Restore();
467
468 canvas.Save();
469 canvas.Translate({100, 400, 0});
470 canvas.DrawCircle({100, 100}, 100, paint);
471 canvas.Restore();
472 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
473 }

References impeller::Paint::color_source, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kRepeat, impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::Canvas::Translate().

## ◆ TEST_P() [41/419]

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

Definition at line 864 of file aiks_unittests.cc.

864 {
865 Canvas canvas;
866 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
867
868 ASSERT_TRUE(RenderTextInCanvasSkia(
869 GetContext(), canvas, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture));
870 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
871 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), kFontFixture, and RenderTextInCanvasSkia().

## ◆ TEST_P() [42/419]

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

Definition at line 886 of file aiks_unittests.cc.

886 {
887 Canvas canvas;
888 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
889
890 ASSERT_TRUE(RenderTextInCanvasSkia(
891 GetContext(), canvas, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
892 {.color = Color::Black().WithAlpha(0.5)}));
893 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
894 }

References impeller::Color::Black(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), kFontFixture, RenderTextInCanvasSkia(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [43/419]

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

Definition at line 873 of file aiks_unittests.cc.

873 {
874 Canvas canvas;
875 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
876
877 ASSERT_TRUE(RenderTextInCanvasSkia(
878 GetContext(), canvas, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
879 TextRenderOptions{.color = Color::Blue(),
880 .mask_blur_descriptor = Paint::MaskBlurDescriptor{
881 .style = FilterContents::BlurStyle::kNormal,
882 .sigma = Sigma(4)}}));
883 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
884 }

References impeller::Color::Blue(), impeller::testing::TextRenderOptions::color, impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), kFontFixture, impeller::FilterContents::kNormal, RenderTextInCanvasSkia(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [44/419]

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

Definition at line 57 of file aiks_blur_unittests.cc.

57 {
58 // This case triggers the ForegroundAdvancedBlend path. The color filter
59 // should apply to the color only, and respect the alpha mask.
60 Canvas canvas;
61 canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
62 canvas.DrawCircle({400, 400}, 200,
63 {
64 .color = Color::Grey(),
65 .color_filter = ColorFilter::MakeBlend(
66 BlendMode::kColor, Color::Green()),
67 .mask_blur_descriptor =
68 Paint::MaskBlurDescriptor{
69 .style = FilterContents::BlurStyle::kNormal,
70 .sigma = Radius(20),
71 },
72 });
73 canvas.Restore();
74
75 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
76 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Color::Grey(), impeller::kColor, impeller::FilterContents::kNormal, impeller::ColorFilter::MakeBlend(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [45/419]

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

Definition at line 36 of file aiks_blur_unittests.cc.

36 {
37 // This case triggers the ForegroundPorterDuffBlend path. The color filter
38 // should apply to the color only, and respect the alpha mask.
39 Canvas canvas;
40 canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
41 canvas.DrawCircle({400, 400}, 200,
42 {
43 .color = Color::White(),
44 .color_filter = ColorFilter::MakeBlend(
45 BlendMode::kSource, Color::Green()),
46 .mask_blur_descriptor =
47 Paint::MaskBlurDescriptor{
48 .style = FilterContents::BlurStyle::kNormal,
49 .sigma = Radius(20),
50 },
51 });
52 canvas.Restore();
53
54 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
55 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kNormal, impeller::kSource, impeller::ColorFilter::MakeBlend(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Color::White().

## ◆ TEST_P() [46/419]

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

Definition at line 604 of file aiks_gradient_unittests.cc.

604 {
605 std::vector<Color> colors = {Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF),
606 Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF),
607 Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF),
608 Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF)};
609 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
610
611 std::array<ColorSource, 3> color_sources = {
612 ColorSource::MakeLinearGradient({0, 0}, {100, 100}, colors, stops,
613 Entity::TileMode::kDecal, {}),
614 ColorSource::MakeRadialGradient({100, 100}, 100, colors, stops,
615 Entity::TileMode::kDecal, {}),
616 ColorSource::MakeSweepGradient({100, 100}, Degrees(45), Degrees(135),
617 colors, stops, Entity::TileMode::kDecal,
618 {}),
619 };
620
621 Canvas canvas;
622 Paint paint;
623 paint.color = Color::White();
624 canvas.DrawRect(Rect::MakeLTRB(0, 0, 605, 205), paint);
625 for (int i = 0; i < 3; i++) {
626 canvas.Save();
627 canvas.Translate({i * 200.0f, 0, 0});
628 paint.color_source = color_sources[i];
629 canvas.DrawRect(Rect::MakeLTRB(0, 0, 200, 200), paint);
630 canvas.Restore();
631 }
632 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
633 }

References impeller::Paint::color, impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kDecal, impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeLTRB(), impeller::ColorSource::MakeRadialGradient(), impeller::Color::MakeRGBA8(), impeller::ColorSource::MakeSweepGradient(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::Translate(), and impeller::Color::White().

## ◆ TEST_P() [47/419]

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

Definition at line 545 of file aiks_unittests.cc.

545 {
546 Canvas canvas;
547
548 Paint red;
549 red.color = Color::Red();
550 Paint green;
551 green.color = Color::Green().WithAlpha(0.5);
552 Paint blue;
553 blue.color = Color::Blue();
554
555 Paint alpha;
556 alpha.color = Color::Red().WithAlpha(0.5);
557
558 canvas.SaveLayer(alpha);
559
560 canvas.DrawRect(Rect::MakeXYWH(000, 000, 100, 100), red);
561 canvas.DrawRect(Rect::MakeXYWH(020, 020, 100, 100), green);
562 canvas.DrawRect(Rect::MakeXYWH(040, 040, 100, 100), blue);
563
564 canvas.Restore();
565
566 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
567 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [48/419]

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

Definition at line 87 of file aiks_unittests.cc.

87 {
88 Canvas canvas;
89 Paint paint;
90 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
91 paint.color = Color::Red();
92 canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
93 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
94 }

References impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::TPoint< Scalar >::MakeXY(), and impeller::Color::Red().

## ◆ TEST_P() [49/419]

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

Definition at line 244 of file aiks_unittests.cc.

244 {
245 Canvas canvas;
246 Paint paint;
247 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
248 Size image_half_size = Size(image->GetSize()) * 0.5;
249
250 // Render the bottom right quarter of the source image in a stretched rect.
251 auto source_rect = Rect::MakeSize(image_half_size);
252 source_rect = source_rect.Shift(Point(image_half_size));
253
254 canvas.DrawImageRect(image, source_rect, Rect::MakeXYWH(100, 100, 600, 600),
255 paint);
256 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
257 }

References impeller::Canvas::DrawImageRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeSize(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [50/419]

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

Definition at line 96 of file aiks_unittests.cc.

96 {
97 Canvas canvas;
98 Paint paint;
99 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
100 paint.color = Color::Red();
101 paint.color_filter =
102 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow());
103 paint.invert_colors = true;
104
105 canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
106 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
107 }

References impeller::Paint::color, impeller::Paint::color_filter, impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::invert_colors, impeller::kSourceOver, impeller::ColorFilter::MakeBlend(), impeller::TPoint< Scalar >::MakeXY(), impeller::Color::Red(), and impeller::Color::Yellow().

## ◆ TEST_P() [51/419]

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

Definition at line 847 of file aiks_unittests.cc.

847 {
848 Canvas canvas;
849 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
850
851 ASSERT_TRUE(RenderTextInCanvasSkia(
852 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
853 "HomemadeApple.ttf"));
854 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
855 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and RenderTextInCanvasSkia().

## ◆ TEST_P() [52/419]

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

Definition at line 45 of file aiks_gradient_unittests.cc.

45 {
46 CanRenderLinearGradient(this, Entity::TileMode::kClamp);
47 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [53/419]

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

Definition at line 54 of file aiks_gradient_unittests.cc.

54 {
55 CanRenderLinearGradient(this, Entity::TileMode::kDecal);
56 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [54/419]

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

Definition at line 58 of file aiks_gradient_unittests.cc.

58 {
59 Canvas canvas;
60 canvas.Scale(GetContentScale());
61 Paint paint;
62 canvas.Translate({100.0f, 0, 0});
63
64 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
65 Color{0.1294, 0.5882, 0.9529, 0.0}};
66 std::vector<Scalar> stops = {0.0, 1.0};
67
68 paint.color_source = ColorSource::MakeLinearGradient(
69 {0, 0}, {200, 200}, std::move(colors), std::move(stops),
70 Entity::TileMode::kDecal, {});
71 // Overlay the gradient with 25% green. This should appear as the entire
72 // rectangle being drawn with 25% green, including the border area outside the
73 // decal gradient.
74 paint.color_filter = ColorFilter::MakeBlend(BlendMode::kSourceOver,
75 Color::Green().WithAlpha(0.25));
76
77 paint.color = Color(1.0, 1.0, 1.0, 1.0);
78 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
79 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
80 }

References impeller::Paint::color, impeller::Paint::color_filter, impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kDecal, impeller::kSourceOver, impeller::ColorFilter::MakeBlend(), impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [55/419]

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

Definition at line 257 of file aiks_gradient_unittests.cc.

257 {
258 CanRenderLinearGradientManyColors(this, Entity::TileMode::kClamp);
259 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [56/419]

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

Definition at line 266 of file aiks_gradient_unittests.cc.

266 {
267 CanRenderLinearGradientManyColors(this, Entity::TileMode::kDecal);
268 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [57/419]

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

Definition at line 263 of file aiks_gradient_unittests.cc.

263 {
264 CanRenderLinearGradientManyColors(this, Entity::TileMode::kMirror);
265 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [58/419]

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

Definition at line 260 of file aiks_gradient_unittests.cc.

260 {
261 CanRenderLinearGradientManyColors(this, Entity::TileMode::kRepeat);
262 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [59/419]

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

Definition at line 300 of file aiks_gradient_unittests.cc.

300 {
301 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
302 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
303 const Entity::TileMode tile_modes[] = {
304 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
305 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
306
307 static int selected_tile_mode = 0;
308 static Matrix matrix = {
309 1, 0, 0, 0, //
310 0, 1, 0, 0, //
311 0, 0, 1, 0, //
312 0, 0, 0, 1 //
313 };
314 if (AiksTest::ImGuiBegin("Controls", nullptr,
315 ImGuiWindowFlags_AlwaysAutoResize)) {
316 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
317 sizeof(tile_mode_names) / sizeof(char*));
318 std::string label = "##1";
319 for (int i = 0; i < 4; i++) {
320 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
321 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
322 label[2]++;
323 }
324 ImGui::End();
325 }
326
327 Canvas canvas;
328 Paint paint;
329 canvas.Translate({100.0, 100.0, 0});
330 auto tile_mode = tile_modes[selected_tile_mode];
331
332 std::vector<Color> colors = {
333 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
334 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
335 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
336 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
337 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
338 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
339 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
340 std::vector<Scalar> stops = {
341 0.0, 2.0 / 62.0, 4.0 / 62.0, 8.0 / 62.0, 16.0 / 62.0, 32.0 / 62.0, 1.0,
342 };
343
344 paint.color_source = ColorSource::MakeLinearGradient(
345 {0, 0}, {200, 200}, std::move(colors), std::move(stops), tile_mode, {});
346
347 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
348 return canvas.EndRecordingAsPicture();
349 };
350 ASSERT_TRUE(OpenPlaygroundHere(callback));
351 }

References impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::AiksPlayground::ImGuiBegin(), impeller::Entity::kClamp, impeller::Entity::kDecal, impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Translate(), and impeller::Matrix::vec.

## ◆ TEST_P() [60/419]

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

Definition at line 353 of file aiks_gradient_unittests.cc.

353 {
354 Canvas canvas;
355
356 Paint paint = {
357 .color = Color::White(),
358 .color_source = ColorSource::MakeLinearGradient(
359 {200, 200}, {400, 400},
360 {Color::Red(), Color::White(), Color::Red(), Color::White(),
361 Color::Red(), Color::White(), Color::Red(), Color::White(),
362 Color::Red(), Color::White(), Color::Red()},
363 {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0},
364 Entity::TileMode::kClamp, {}),
365 .mask_blur_descriptor =
366 Paint::MaskBlurDescriptor{
367 .style = FilterContents::BlurStyle::kNormal,
368 .sigma = Sigma(20),
369 },
370 };
371
372 canvas.DrawCircle({300, 300}, 200, paint);
373 canvas.DrawRect(Rect::MakeLTRB(100, 300, 500, 600), paint);
374
375 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
376 }

References impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Color::Red(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Color::White().

## ◆ TEST_P() [61/419]

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

Definition at line 51 of file aiks_gradient_unittests.cc.

51 {
52 CanRenderLinearGradient(this, Entity::TileMode::kMirror);
53 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [62/419]

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

Definition at line 48 of file aiks_gradient_unittests.cc.

48 {
49 CanRenderLinearGradient(this, Entity::TileMode::kRepeat);
50 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [63/419]

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

Definition at line 296 of file aiks_gradient_unittests.cc.

296 {
297 CanRenderLinearGradientWayManyColors(this, Entity::TileMode::kClamp);
298 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [64/419]

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

Definition at line 102 of file aiks_gradient_unittests.cc.

102 {
103 CanRenderLinearGradientWithDithering(this, false);
104 }

References CanRenderLinearGradientWithDithering().

## ◆ TEST_P() [65/419]

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

Definition at line 106 of file aiks_gradient_unittests.cc.

106 {
107 CanRenderLinearGradientWithDithering(this, true);
108 } // namespace

References CanRenderLinearGradientWithDithering().

## ◆ TEST_P() [66/419]

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

Definition at line 217 of file aiks_gradient_unittests.cc.

217 {
218 CanRenderLinearGradientWithOverlappingStops(this, Entity::TileMode::kClamp);
219 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [67/419]

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

Definition at line 23 of file aiks_blur_unittests.cc.

23 {
24 Canvas canvas;
25 canvas.DrawCircle({400, 400}, 300,
26 {.color = Color::Green(),
27 .mask_blur_descriptor = Paint::MaskBlurDescriptor{
28 .style = FilterContents::BlurStyle::kNormal,
29 .sigma = Sigma(99999),
30 }});
31 canvas.Restore();
32
33 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
34 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kNormal, impeller::Canvas::Restore(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [68/419]

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

Definition at line 339 of file aiks_unittests.cc.

339 {
340 Canvas canvas;
341 Paint paint;
342 paint.color = Color::Fuchsia();
343 canvas.Save();
344 canvas.ClipPath(PathBuilder{}.AddCircle({200, 400}, 300).TakePath());
345 canvas.Restore();
346 canvas.ClipPath(PathBuilder{}.AddCircle({600, 400}, 300).TakePath());
347 canvas.ClipPath(PathBuilder{}.AddCircle({400, 600}, 300).TakePath());
348 canvas.DrawRect(Rect::MakeXYWH(200, 200, 400, 400), paint);
349 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
350 }

References impeller::PathBuilder::AddCircle(), impeller::Canvas::ClipPath(), impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Fuchsia(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), and impeller::Canvas::Save().

## ◆ TEST_P() [69/419]

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

Tests that the debug checkerboard displays for offscreen textures when enabled. Most of the complexity here is just to future proof by making pass collapsing hard.

Definition at line 2649 of file aiks_unittests.cc.

2649 {
2650 Canvas canvas;
2651 canvas.debug_options.offscreen_texture_checkerboard = true;
2652
2653 canvas.DrawPaint({.color = Color::AntiqueWhite()});
2654 canvas.DrawCircle({400, 300}, 200,
2655 {.color = Color::CornflowerBlue().WithAlpha(0.75)});
2656
2657 canvas.SaveLayer({.blend_mode = BlendMode::kMultiply});
2658 {
2659 canvas.DrawCircle({500, 400}, 200,
2660 {.color = Color::DarkBlue().WithAlpha(0.75)});
2661 canvas.DrawCircle({550, 450}, 200,
2662 {.color = Color::LightCoral().WithAlpha(0.75),
2663 .blend_mode = BlendMode::kLuminosity});
2664 }
2665 canvas.Restore();
2666
2667 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2668 }

References impeller::Color::AntiqueWhite(), impeller::Color::CornflowerBlue(), impeller::Color::DarkBlue(), impeller::Canvas::debug_options, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kLuminosity, impeller::kMultiply, impeller::Color::LightCoral(), impeller::Canvas::DebugOptions::offscreen_texture_checkerboard, impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [70/419]

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

Definition at line 401 of file aiks_path_unittests.cc.

401 {
402 Canvas canvas;
403
404 Paint paint;
405 paint.color = Color::Red();
406
407 PathBuilder::RoundingRadii radii;
408 radii.top_left = {50, 50};
409 radii.top_right = {50, 50};
410 radii.bottom_right = {50, 50};
411 radii.bottom_left = {50, 50};
412
413 const Scalar kTriangleHeight = 100;
414 canvas.Translate(Vector2(200, 200));
415 // Form a path similar to the Material drop slider value indicator. Both
416 // shapes should render identically side-by-side.
417 {
418 auto path =
419 PathBuilder{}
420 .MoveTo({0, kTriangleHeight})
421 .LineTo({-kTriangleHeight / 2.0f, 0})
422 .LineTo({kTriangleHeight / 2.0f, 0})
423 .Close()
424 .AddRoundedRect(
425 Rect::MakeXYWH(-kTriangleHeight / 2.0f, -kTriangleHeight / 2.0f,
426 kTriangleHeight, kTriangleHeight),
427 radii)
428 .TakePath();
429
430 canvas.DrawPath(path, paint);
431 }
432 canvas.Translate(Vector2(100, 0));
433 {
434 auto path =
435 PathBuilder{}
436 .MoveTo({0, kTriangleHeight})
437 .LineTo({-kTriangleHeight / 2.0f, 0})
438 .LineTo({0, -10})
439 .LineTo({kTriangleHeight / 2.0f, 0})
440 .Close()
441 .AddRoundedRect(
442 Rect::MakeXYWH(-kTriangleHeight / 2.0f, -kTriangleHeight / 2.0f,
443 kTriangleHeight, kTriangleHeight),
444 radii)
445 .TakePath();
446
447 canvas.DrawPath(path, paint);
448 }
449
450 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
451 }

References impeller::PathBuilder::RoundingRadii::bottom_left, impeller::PathBuilder::RoundingRadii::bottom_right, impeller::Close(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::LineTo(), impeller::TRect< Scalar >::MakeXYWH(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::PathBuilder::RoundingRadii::top_left, impeller::PathBuilder::RoundingRadii::top_right, and impeller::Canvas::Translate().

## ◆ TEST_P() [71/419]

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

Definition at line 378 of file aiks_gradient_unittests.cc.

378 {
379 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
380 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
381 const Entity::TileMode tile_modes[] = {
382 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
383 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
384
385 static int selected_tile_mode = 0;
386 static Matrix matrix = {
387 1, 0, 0, 0, //
388 0, 1, 0, 0, //
389 0, 0, 1, 0, //
390 0, 0, 0, 1 //
391 };
392 if (AiksTest::ImGuiBegin("Controls", nullptr,
393 ImGuiWindowFlags_AlwaysAutoResize)) {
394 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
395 sizeof(tile_mode_names) / sizeof(char*));
396 std::string label = "##1";
397 for (int i = 0; i < 4; i++) {
398 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
399 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
400 label[2]++;
401 }
402 ImGui::End();
403 }
404
405 Canvas canvas;
406 Paint paint;
407 canvas.Translate({100.0, 100.0, 0});
408 auto tile_mode = tile_modes[selected_tile_mode];
409
410 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
411 Color{0.1294, 0.5882, 0.9529, 1.0}};
412 std::vector<Scalar> stops = {0.0, 1.0};
413
414 paint.color_source = ColorSource::MakeRadialGradient(
415 {100, 100}, 100, std::move(colors), std::move(stops), tile_mode, {});
416
417 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
418 return canvas.EndRecordingAsPicture();
419 };
420 ASSERT_TRUE(OpenPlaygroundHere(callback));
421 }

References impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::AiksPlayground::ImGuiBegin(), impeller::Entity::kClamp, impeller::Entity::kDecal, impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeRadialGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Translate(), and impeller::Matrix::vec.

## ◆ TEST_P() [72/419]

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

Definition at line 423 of file aiks_gradient_unittests.cc.

423 {
424 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
425 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
426 const Entity::TileMode tile_modes[] = {
427 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
428 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
429
430 static int selected_tile_mode = 0;
431 static Matrix matrix = {
432 1, 0, 0, 0, //
433 0, 1, 0, 0, //
434 0, 0, 1, 0, //
435 0, 0, 0, 1 //
436 };
437 if (AiksTest::ImGuiBegin("Controls", nullptr,
438 ImGuiWindowFlags_AlwaysAutoResize)) {
439 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
440 sizeof(tile_mode_names) / sizeof(char*));
441 std::string label = "##1";
442 for (int i = 0; i < 4; i++) {
443 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
444 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
445 label[2]++;
446 }
447 ImGui::End();
448 }
449
450 Canvas canvas;
451 Paint paint;
452 canvas.Translate({100.0, 100.0, 0});
453 auto tile_mode = tile_modes[selected_tile_mode];
454
455 std::vector<Color> colors = {
456 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
457 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
458 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
459 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
460 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
461 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
462 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
463 std::vector<Scalar> stops = {
464 0.0,
465 (1.0 / 6.0) * 1,
466 (1.0 / 6.0) * 2,
467 (1.0 / 6.0) * 3,
468 (1.0 / 6.0) * 4,
469 (1.0 / 6.0) * 5,
470 1.0,
471 };
472
473 paint.color_source = ColorSource::MakeRadialGradient(
474 {100, 100}, 100, std::move(colors), std::move(stops), tile_mode, {});
475
476 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
477 return canvas.EndRecordingAsPicture();
478 };
479 ASSERT_TRUE(OpenPlaygroundHere(callback));
480 }

References impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::AiksPlayground::ImGuiBegin(), impeller::Entity::kClamp, impeller::Entity::kDecal, impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeRadialGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Translate(), and impeller::Matrix::vec.

## ◆ TEST_P() [73/419]

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

Definition at line 129 of file aiks_gradient_unittests.cc.

129 {
130 CanRenderRadialGradientWithDithering(this, false);
131 }

References CanRenderRadialGradientWithDithering().

## ◆ TEST_P() [74/419]

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

Definition at line 133 of file aiks_gradient_unittests.cc.

133 {
134 CanRenderRadialGradientWithDithering(this, true);
135 }

References CanRenderRadialGradientWithDithering().

## ◆ TEST_P() [75/419]

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

Definition at line 686 of file aiks_unittests.cc.

686 {
687 Canvas canvas;
688
689 Paint paint;
690 paint.color = Color::Red();
691
692 PathBuilder::RoundingRadii radii;
693 radii.top_left = {50, 25};
694 radii.top_right = {25, 50};
695 radii.bottom_right = {50, 25};
696 radii.bottom_left = {25, 50};
697
698 auto path = PathBuilder{}
699 .AddRoundedRect(Rect::MakeXYWH(100, 100, 500, 500), radii)
700 .TakePath();
701
702 canvas.DrawPath(path, paint);
703
704 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
705 }

References impeller::PathBuilder::AddRoundedRect(), impeller::PathBuilder::RoundingRadii::bottom_left, impeller::PathBuilder::RoundingRadii::bottom_right, impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::PathBuilder::TakePath(), impeller::PathBuilder::RoundingRadii::top_left, and impeller::PathBuilder::RoundingRadii::top_right.

## ◆ TEST_P() [76/419]

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

Definition at line 259 of file aiks_unittests.cc.

259 {
260 Canvas canvas;
261 canvas.Scale(GetContentScale());
262 Paint paint;
263
264 paint.color = Color::White();
265 canvas.DrawPaint(paint);
266
267 auto draw = [&canvas](const Paint& paint, Scalar x, Scalar y) {
268 canvas.Save();
269 canvas.Translate({x, y});
270 {
271 canvas.Save();
272 canvas.ClipRect(Rect::MakeLTRB(50, 50, 150, 150));
273 canvas.DrawPaint(paint);
274 canvas.Restore();
275 }
276 {
277 canvas.Save();
278 canvas.ClipOval(Rect::MakeLTRB(200, 50, 300, 150));
279 canvas.DrawPaint(paint);
280 canvas.Restore();
281 }
282 {
283 canvas.Save();
284 canvas.ClipRRect(Rect::MakeLTRB(50, 200, 150, 300), {20, 20});
285 canvas.DrawPaint(paint);
286 canvas.Restore();
287 }
288 {
289 canvas.Save();
290 canvas.ClipRRect(Rect::MakeLTRB(200, 230, 300, 270), {20, 20});
291 canvas.DrawPaint(paint);
292 canvas.Restore();
293 }
294 {
295 canvas.Save();
296 canvas.ClipRRect(Rect::MakeLTRB(230, 200, 270, 300), {20, 20});
297 canvas.DrawPaint(paint);
298 canvas.Restore();
299 }
300 canvas.Restore();
301 };
302
303 paint.color = Color::Blue();
304 draw(paint, 0, 0);
305
306 std::vector<Color> gradient_colors = {
307 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
308 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
309 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
310 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
311 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
312 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
313 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
314 std::vector<Scalar> stops = {
315 0.0,
316 (1.0 / 6.0) * 1,
317 (1.0 / 6.0) * 2,
318 (1.0 / 6.0) * 3,
319 (1.0 / 6.0) * 4,
320 (1.0 / 6.0) * 5,
321 1.0,
322 };
323 auto texture = CreateTextureForFixture("airplane.jpg",
324 /*enable_mipmapping=*/true);
325
326 paint.color_source = ColorSource::MakeRadialGradient(
327 {500, 600}, 75, std::move(gradient_colors), std::move(stops),
328 Entity::TileMode::kMirror, {});
329 draw(paint, 0, 300);
330
331 paint.color_source = ColorSource::MakeImage(
332 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
333 Matrix::MakeTranslation({0, 0}));
334 draw(paint, 300, 0);
335
336 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
337 }

References impeller::Color::Blue(), impeller::Canvas::ClipOval(), impeller::Canvas::ClipRect(), impeller::Canvas::ClipRRect(), impeller::Paint::color, impeller::Paint::color_source, impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeImage(), impeller::TRect< Scalar >::MakeLTRB(), impeller::ColorSource::MakeRadialGradient(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::Scale(), impeller::Canvas::Translate(), and impeller::Color::White().

## ◆ TEST_P() [77/419]

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

Definition at line 76 of file aiks_path_unittests.cc.

76 {
77 Canvas canvas;
78
79 Paint paint;
80 paint.color = Color::Red();
81 paint.style = Paint::Style::kStroke;
82 paint.stroke_width = 200;
83
84 Rect rect = Rect::MakeXYWH(100, 100, 200, 200);
85 PathBuilder builder;
86 builder.AddArc(rect, Degrees(0), Degrees(90), false);
87
88 canvas.DrawPath(builder.TakePath(), paint);
89 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
90 }

References impeller::PathBuilder::AddArc(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Paint::stroke_width, impeller::Paint::style, and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [78/419]

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

Definition at line 92 of file aiks_path_unittests.cc.

92 {
93 Canvas canvas;
94
95 Paint paint;
96 paint.color = Color::Red();
97 paint.style = Paint::Style::kStroke;
98 paint.stroke_width = 20;
99
100 PathBuilder builder;
101 builder.AddCubicCurve({0, 200}, {50, 400}, {350, 0}, {400, 200});
102
103 canvas.DrawPath(builder.TakePath(), paint);
104 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
105 }

References impeller::PathBuilder::AddCubicCurve(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, impeller::Color::Red(), impeller::Paint::stroke_width, impeller::Paint::style, and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [79/419]

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

Definition at line 45 of file aiks_path_unittests.cc.

45 {
46 Canvas canvas;
47 Paint paint;
48 paint.color = Color::Red();
49 paint.stroke_width = 20.0;
50 paint.style = Paint::Style::kStroke;
51 canvas.DrawPath(PathBuilder{}.AddLine({200, 100}, {800, 100}).TakePath(),
52 paint);
53 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
54 }

References impeller::PathBuilder::AddLine(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, impeller::Color::Red(), impeller::Paint::stroke_width, and impeller::Paint::style.

## ◆ TEST_P() [80/419]

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

Definition at line 502 of file aiks_gradient_unittests.cc.

502 {
503 CanRenderSweepGradient(this, Entity::TileMode::kClamp);
504 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [81/419]

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

Definition at line 511 of file aiks_gradient_unittests.cc.

511 {
512 CanRenderSweepGradient(this, Entity::TileMode::kDecal);
513 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [82/419]

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

Definition at line 549 of file aiks_gradient_unittests.cc.

549 {
550 CanRenderSweepGradientManyColors(this, Entity::TileMode::kClamp);
551 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [83/419]

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

Definition at line 558 of file aiks_gradient_unittests.cc.

558 {
559 CanRenderSweepGradientManyColors(this, Entity::TileMode::kDecal);
560 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [84/419]

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

Definition at line 555 of file aiks_gradient_unittests.cc.

555 {
556 CanRenderSweepGradientManyColors(this, Entity::TileMode::kMirror);
557 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [85/419]

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

Definition at line 552 of file aiks_gradient_unittests.cc.

552 {
553 CanRenderSweepGradientManyColors(this, Entity::TileMode::kRepeat);
554 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [86/419]

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

Definition at line 508 of file aiks_gradient_unittests.cc.

508 {
509 CanRenderSweepGradient(this, Entity::TileMode::kMirror);
510 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [87/419]

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

Definition at line 505 of file aiks_gradient_unittests.cc.

505 {
506 CanRenderSweepGradient(this, Entity::TileMode::kRepeat);
507 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [88/419]

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

Definition at line 158 of file aiks_gradient_unittests.cc.

158 {
159 CanRenderSweepGradientWithDithering(this, false);
160 }

References CanRenderSweepGradientWithDithering().

## ◆ TEST_P() [89/419]

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

Definition at line 162 of file aiks_gradient_unittests.cc.

162 {
163 CanRenderSweepGradientWithDithering(this, true);
164 }

References CanRenderSweepGradientWithDithering().

## ◆ TEST_P() [90/419]

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

Definition at line 781 of file aiks_unittests.cc.

781 {
782 Canvas canvas;
783 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
784 ASSERT_TRUE(RenderTextInCanvasSkia(
785 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
786 "Roboto-Regular.ttf"));
787 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
788 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and RenderTextInCanvasSkia().

## ◆ TEST_P() [91/419]

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

Definition at line 790 of file aiks_unittests.cc.

790 {
791 Canvas canvas;
792 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
793 ASSERT_TRUE(RenderTextInCanvasSTB(
794 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
795 "Roboto-Regular.ttf"));
796
797 SetTypographerContext(TypographerContextSTB::Make());
798 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
799 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::TypographerContextSTB::Make(), and RenderTextInCanvasSTB().

## ◆ TEST_P() [92/419]

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

Definition at line 896 of file aiks_unittests.cc.

896 {
897 Canvas canvas;
898 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
899
900 canvas.Translate({100, 100});
901 canvas.Scale(Vector2{0.5, 0.5});
902
903 // Blend the layer with the parent pass using kClear to expose the coverage.
904 canvas.SaveLayer({.blend_mode = BlendMode::kClear});
905 ASSERT_TRUE(RenderTextInCanvasSkia(
906 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
907 "Roboto-Regular.ttf"));
908 canvas.Restore();
909
910 // Render the text again over the cleared coverage rect.
911 ASSERT_TRUE(RenderTextInCanvasSkia(
912 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
913 "Roboto-Regular.ttf"));
914
915 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
916 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kClear, RenderTextInCanvasSkia(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [93/419]

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

Definition at line 918 of file aiks_unittests.cc.

918 {
919 Canvas canvas;
920 canvas.Translate({200, 150});
921
922 // Construct the text blob.
923 auto mapping = flutter::testing::OpenFixtureAsSkData("wtf.otf");
924 ASSERT_NE(mapping, nullptr);
925
926 Scalar font_size = 80;
927 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
928 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
929
930 Paint text_paint;
931 text_paint.color = Color::Blue().WithAlpha(0.8);
932
933 struct {
934 Point position;
935 const char* text;
936 } text[] = {{Point(0, 0), "0F0F0F0"},
937 {Point(1, 2), "789"},
938 {Point(1, 3), "456"},
939 {Point(1, 4), "123"},
940 {Point(0, 6), "0F0F0F0"}};
941 for (auto& t : text) {
942 canvas.Save();
943 canvas.Translate(t.position * Point(font_size * 2, font_size * 1.1));
944 {
945 auto blob = SkTextBlob::MakeFromString(t.text, sk_font);
946 ASSERT_NE(blob, nullptr);
947 auto frame = MakeTextFrameFromTextBlobSkia(blob);
948 canvas.DrawTextFrame(frame, Point(), text_paint);
949 }
950 canvas.Restore();
951 }
952
953 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
954 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawTextFrame(), impeller::Canvas::EndRecordingAsPicture(), impeller::MakeTextFrameFromTextBlobSkia(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::Translate(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [94/419]

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

Definition at line 66 of file aiks_path_unittests.cc.

66 {
67 Canvas canvas;
68 Paint paint;
69 paint.color = Color::Red();
70 paint.stroke_width = 100.0;
71 paint.style = Paint::Style::kStroke;
72 canvas.DrawPath(PathBuilder{}.AddCircle({100, 100}, 50).TakePath(), paint);
73 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
74 }

References impeller::PathBuilder::AddCircle(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, impeller::Color::Red(), impeller::Paint::stroke_width, and impeller::Paint::style.

## ◆ TEST_P() [95/419]

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

Definition at line 223 of file aiks_unittests.cc.

223 {
224 CanRenderTiledTexture(this, Entity::TileMode::kClamp);
225 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [96/419]

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

Definition at line 239 of file aiks_unittests.cc.

239 {
240 CanRenderTiledTexture(this, Entity::TileMode::kClamp,
241 Matrix::MakeTranslation({172.f, 172.f, 0.f}));
242 }

References impeller::Entity::kClamp, and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [97/419]

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

Definition at line 235 of file aiks_unittests.cc.

235 {
236 CanRenderTiledTexture(this, Entity::TileMode::kDecal);
237 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [98/419]

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

Definition at line 231 of file aiks_unittests.cc.

231 {
232 CanRenderTiledTexture(this, Entity::TileMode::kMirror);
233 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [99/419]

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

Definition at line 227 of file aiks_unittests.cc.

227 {
228 CanRenderTiledTexture(this, Entity::TileMode::kRepeat);
229 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [100/419]

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 2629 of file aiks_unittests.cc.

2629 {
2630 Canvas canvas;
2631 canvas.DrawPaint({.color = Color::Red()});
2632
2633 // Draw two overlapping subpixel circles.
2634 canvas.SaveLayer({});
2635 canvas.DrawCircle({100, 100}, 0.1, {.color = Color::Yellow()});
2636 canvas.Restore();
2637 canvas.SaveLayer({});
2638 canvas.DrawCircle({100, 100}, 0.1, {.color = Color::Yellow()});
2639 canvas.Restore();
2640
2641 canvas.DrawPaint({.color = Color::Green()});
2642
2643 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2644 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::Yellow().

## ◆ TEST_P() [101/419]

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

Definition at line 389 of file aiks_unittests.cc.

389 {
390 Canvas canvas;
391
392 // Cover the whole canvas with red.
393 canvas.DrawPaint({.color = Color::Red()});
394
395 canvas.Save();
396
397 // Append two clips, the second resulting in empty coverage.
398 canvas.ClipPath(
399 PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath());
400 canvas.ClipPath(
401 PathBuilder{}.AddRect(Rect::MakeXYWH(300, 300, 100, 100)).TakePath());
402
403 // Restore to no clips.
404 canvas.Restore();
405
406 // Replace the whole canvas with green.
407 canvas.DrawPaint({.color = Color::Green()});
408
409 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
410 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::ClipPath(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [102/419]

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

Definition at line 430 of file aiks_unittests.cc.

430 {
431 Canvas canvas;
432
433 Paint red;
434 red.color = Color::Red();
435
436 Paint alpha;
437 alpha.color = Color::Red().WithAlpha(0.5);
438
439 canvas.SaveLayer(alpha);
440
441 canvas.DrawCircle({125, 125}, 125, red);
442
443 canvas.Restore();
444
445 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
446 }

References impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [103/419]

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

Definition at line 60 of file aiks_unittests.cc.

60 {
61 Canvas canvas;
62 ASSERT_EQ(canvas.GetSaveCount(), 1u);
63 ASSERT_EQ(canvas.Restore(), false);
64
65 canvas.Translate(Size{100, 100});
66 canvas.Save();
67 ASSERT_EQ(canvas.GetSaveCount(), 2u);
68 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(),
69 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
70 ASSERT_TRUE(canvas.Restore());
71 ASSERT_EQ(canvas.GetSaveCount(), 1u);
72 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(),
73 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
74 }

References ASSERT_MATRIX_NEAR, impeller::Canvas::GetCurrentTransform(), impeller::Canvas::GetSaveCount(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::Canvas::Translate().

## ◆ TEST_P() [104/419]

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

Definition at line 51 of file aiks_unittests.cc.

51 {
52 Canvas canvas;
53 Matrix identity;
54 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(), identity);
55 canvas.Translate(Size{100, 100});
56 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(),
57 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
58 }

References ASSERT_MATRIX_NEAR, impeller::Canvas::GetCurrentTransform(), impeller::Matrix::MakeTranslation(), and impeller::Canvas::Translate().

## ◆ TEST_P() [105/419]

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

Definition at line 3050 of file aiks_unittests.cc.

3050 {
3051 auto capture_context = CaptureContext::MakeAllowlist({"TestDocument"});
3052
3053 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
3054 Canvas canvas;
3055
3056 capture_context.Rewind();
3057 auto document = capture_context.GetDocument("TestDocument");
3058
3059 auto color = document.AddColor("Background color", Color::CornflowerBlue());
3060 canvas.DrawPaint({.color = color});
3061
3062 if (AiksTest::ImGuiBegin("TestDocument", nullptr,
3063 ImGuiWindowFlags_AlwaysAutoResize)) {
3064 document.GetElement()->properties.Iterate([](CaptureProperty& property) {
3065 property.Invoke({.color = [](CaptureColorProperty& p) {
3066 ImGui::ColorEdit4(p.label.c_str(),
3067 reinterpret_cast<float*>(&p.value));
3068 }});
3069 });
3070 ImGui::End();
3071 }
3072
3073 return canvas.EndRecordingAsPicture();
3074 };
3075 OpenPlaygroundHere(callback);
3076 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::AiksPlayground::ImGuiBegin(), and impeller::CaptureContext::MakeAllowlist().

## ◆ TEST_P() [106/419]

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

Definition at line 3078 of file aiks_unittests.cc.

3078 {
3079 ASSERT_FALSE(GetContext()->capture.IsActive());
3080 }

## ◆ TEST_P() [107/419]

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

Definition at line 3160 of file aiks_unittests.cc.

3160 {
3161 Canvas canvas;
3162 Paint white;
3163 white.color = Color::Blue();
3164 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600.0, 600.0), white);
3165
3166 Paint clear;
3167 clear.blend_mode = BlendMode::kClear;
3168
3169 canvas.DrawCircle(Point::MakeXY(300.0, 300.0), 200.0, clear);
3170 }

References impeller::Paint::blend_mode, impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::kClear, impeller::TPoint< Scalar >::MakeXY(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [108/419]

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

Definition at line 183 of file aiks_blur_unittests.cc.

183 {
184 Canvas canvas;
185 Paint white;
186 white.color = Color::Blue();
187 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600.0, 600.0), white);
188
189 Paint clear;
190 clear.blend_mode = BlendMode::kClear;
191 clear.mask_blur_descriptor = Paint::MaskBlurDescriptor{
192 .style = FilterContents::BlurStyle::kNormal,
193 .sigma = Sigma(20),
194 };
195
196 canvas.DrawCircle(Point::MakeXY(300.0, 300.0), 200.0, clear);
197
198 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
199 }

References impeller::Paint::blend_mode, impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kClear, impeller::FilterContents::kNormal, impeller::TPoint< Scalar >::MakeXY(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Paint::mask_blur_descriptor, and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [109/419]

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

Definition at line 2115 of file aiks_unittests.cc.

2115 {
2116 Canvas canvas;
2117 canvas.SaveLayer({}, std::nullopt,
2118 ImageFilter::MakeBlur(Sigma(3), Sigma(3),
2119 FilterContents::BlurStyle::kNormal,
2120 Entity::TileMode::kClamp));
2121 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
2122 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
2123 .blend_mode = BlendMode::kSourceOver});
2124 canvas.Restore();
2125
2126 Picture picture = canvas.EndRecordingAsPicture();
2127
2128 std::optional<Color> actual_color;
2129 bool found_subpass = false;
2130 picture.pass->IterateAllElements([&](EntityPass::Element& element) -> bool {
2131 if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
2132 actual_color = subpass->get()->GetClearColor();
2133 found_subpass = true;
2134 }
2135 // Fail if the first element isn't a subpass.
2136 return true;
2137 });
2138
2139 EXPECT_TRUE(found_subpass);
2140 EXPECT_FALSE(actual_color.has_value());
2141 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::kSourceOver, impeller::ImageFilter::MakeBlur(), impeller::Picture::pass, impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [110/419]

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

Definition at line 3225 of file aiks_unittests.cc.

3225 {
3226 SetWindowSize({400, 400});
3227 Canvas canvas;
3228 canvas.Scale(GetContentScale());
3229 canvas.DrawRect(Rect::MakeLTRB(200, 200, 300, 300), {.color = Color::Red()});
3230 canvas.SaveLayer({
3231 .image_filter = std::make_shared<MatrixImageFilter>(
3232 Matrix::MakeScale({2, 2, 1}), SamplerDescriptor{}),
3233 });
3234 // Draw a rectangle that would fully cover the parent pass size, but not
3235 // the subpass that it is rendered in.
3236 canvas.DrawRect(Rect::MakeLTRB(0, 0, 400, 400), {.color = Color::Green()});
3237 // Draw a bigger rectangle to force the subpass to be bigger.
3238 canvas.DrawRect(Rect::MakeLTRB(0, 0, 800, 800), {.color = Color::Red()});
3239 canvas.Restore();
3240
3241 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3242 }

References impeller::Color::Green(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Color::Red(), and impeller::Canvas::Scale().

## ◆ TEST_P() [111/419]

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

Definition at line 168 of file aiks_blur_unittests.cc.

168 {
169 Canvas canvas;
170 canvas.Translate(Point(0, -400));
171 Paint paint;
172 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
173 .style = FilterContents::BlurStyle::kNormal,
174 .sigma = Radius{120 * 3},
175 };
176 paint.color = Color::Red();
177 PathBuilder builder{};
178 builder.AddRect(Rect::MakeLTRB(0, 0, 800, 800));
179 canvas.DrawPath(builder.TakePath(), paint);
180 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
181 }

References impeller::PathBuilder::AddRect(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::FilterContents::kNormal, impeller::TRect< Scalar >::MakeLTRB(), impeller::Paint::mask_blur_descriptor, impeller::Color::Red(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Canvas::Translate().

## ◆ TEST_P() [112/419]

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

Definition at line 146 of file aiks_blur_unittests.cc.

146 {
147 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
148 static PlaygroundPoint playground_point(Point(400, 400), 20,
149 Color::Green());
150 auto point = DrawPlaygroundPoint(playground_point);
151
152 Canvas canvas;
153 canvas.Translate(point - Point(400, 400));
154 Paint paint;
155 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
156 .style = FilterContents::BlurStyle::kNormal,
157 .sigma = Radius{120 * 3},
158 };
159 paint.color = Color::Red();
160 PathBuilder builder{};
161 builder.AddRect(Rect::MakeLTRB(0, 0, 800, 800));
162 canvas.DrawPath(builder.TakePath(), paint);
163 return canvas.EndRecordingAsPicture();
164 };
165 ASSERT_TRUE(OpenPlaygroundHere(callback));
166 }

References impeller::PathBuilder::AddRect(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::DrawPlaygroundPoint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kNormal, impeller::TRect< Scalar >::MakeLTRB(), impeller::Paint::mask_blur_descriptor, impeller::Color::Red(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Canvas::Translate().

## ◆ TEST_P() [113/419]

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

Definition at line 2091 of file aiks_unittests.cc.

2091 {
2092 Canvas canvas(Rect::MakeXYWH(0, 0, 100, 100));
2093 canvas.ClipRect(Rect::MakeXYWH(0, 0, 100, 100));
2094 canvas.ClipRect(Rect::MakeXYWH(-100, -100, 300, 300));
2095 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
2096 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
2097 .blend_mode = BlendMode::kSourceOver});
2098
2099 Picture picture = canvas.EndRecordingAsPicture();
2100 auto expected = Color::Red().Blend(Color::CornflowerBlue().WithAlpha(0.75),
2101 BlendMode::kSourceOver);
2102 ASSERT_EQ(picture.pass->GetClearColor(), expected);
2103
2104 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2105 std::shared_ptr<Context> real_context = GetContext();
2106 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2107 AiksContext renderer(mock_context, nullptr);
2108 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
2109
2110 ASSERT_EQ(spy->render_passes_.size(), 1llu);
2111 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2112 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
2113 }

References impeller::Color::Blend(), impeller::Canvas::ClipRect(), impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSource, impeller::kSourceOver, impeller::TRect< Scalar >::MakeXYWH(), impeller::Picture::pass, impeller::Color::Red(), impeller::Picture::ToImage(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [114/419]

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

Definition at line 412 of file aiks_unittests.cc.

412 {
413 std::array<Color, 5> colors = {Color::White(), Color::Black(),
414 Color::SkyBlue(), Color::Red(),
415 Color::Yellow()};
416 Canvas canvas;
417 Paint paint;
418
419 canvas.Translate(Vector3(300, 300));
420 for (int i = 0; i < 15; i++) {
421 canvas.Scale(Vector3(0.8, 0.8));
422
423 paint.color = colors[i % colors.size()];
424 canvas.ClipPath(PathBuilder{}.AddCircle({0, 0}, 300).TakePath());
425 canvas.DrawRect(Rect::MakeXYWH(-300, -300, 600, 600), paint);
426 }
427 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
428 }

References impeller::PathBuilder::AddCircle(), impeller::Color::Black(), impeller::Canvas::ClipPath(), impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Scale(), impeller::Color::SkyBlue(), impeller::Canvas::Translate(), impeller::Color::White(), and impeller::Color::Yellow().

## ◆ TEST_P() [115/419]

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

Definition at line 2143 of file aiks_unittests.cc.

2143 {
2144 Canvas canvas;
2145 canvas.DrawPaint(
2146 {.color = Color::Yellow(), .blend_mode = BlendMode::kSource});
2147 canvas.SaveLayer({.blend_mode = BlendMode::kMultiply});
2148 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
2149 .blend_mode = BlendMode::kSourceOver});
2150
2151 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2152 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kMultiply, impeller::kSource, impeller::kSourceOver, impeller::Canvas::SaveLayer(), impeller::Color::WithAlpha(), and impeller::Color::Yellow().

## ◆ TEST_P() [116/419]

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

Definition at line 2154 of file aiks_unittests.cc.

2154 {
2155 // Bug: https://github.com/flutter/flutter/issues/131576
2156 Canvas canvas;
2157 canvas.DrawPaint(
2158 {.color = Color::Yellow(), .blend_mode = BlendMode::kSource});
2159 canvas.SaveLayer({}, {},
2160 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
2161 FilterContents::BlurStyle::kNormal,
2162 Entity::TileMode::kDecal));
2163 canvas.DrawPaint(
2164 {.color = Color::CornflowerBlue(), .blend_mode = BlendMode::kSourceOver});
2165
2166 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2167 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSource, impeller::kSourceOver, impeller::ImageFilter::MakeBlur(), impeller::Canvas::SaveLayer(), and impeller::Color::Yellow().

## ◆ TEST_P() [117/419]

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

Definition at line 2184 of file aiks_unittests.cc.

2184 {
2185 Canvas canvas;
2186
2187 canvas.SaveLayer({
2188 .color_filter =
2189 ColorFilter::MakeMatrix({.array =
2190 {
2191 -1.0, 0, 0, 1.0, 0, //
2192 0, -1.0, 0, 1.0, 0, //
2193 0, 0, -1.0, 1.0, 0, //
2194 1.0, 1.0, 1.0, 1.0, 0 //
2195 }}),
2196 });
2197
2198 canvas.Translate({500, 300, 0});
2199 canvas.Rotate(Radians(2 * kPi / 3));
2200 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
2201
2202 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2203 }

References impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kPi, impeller::ColorFilter::MakeMatrix(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Rotate(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [118/419]

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 1105 of file aiks_unittests.cc.

1105 {
1106 // Compare with https://fiddle.skia.org/c/@BlendModes
1107
1108 BlendModeSelection blend_modes = GetBlendModeSelection();
1109
1110 auto draw_color_wheel = [](Canvas& canvas) {
1111 /// color_wheel_sampler: r=0 -> fuchsia, r=2pi/3 -> yellow, r=4pi/3 ->
1112 /// cyan domain: r >= 0 (because modulo used is non euclidean)
1113 auto color_wheel_sampler = [](Radians r) {
1114 Scalar x = r.radians / k2Pi + 1;
1115
1116 // https://www.desmos.com/calculator/6nhjelyoaj
1117 auto color_cycle = [](Scalar x) {
1118 Scalar cycle = std::fmod(x, 6.0f);
1119 return std::max(0.0f, std::min(1.0f, 2 - std::abs(2 - cycle)));
1120 };
1121 return Color(color_cycle(6 * x + 1), //
1122 color_cycle(6 * x - 1), //
1123 color_cycle(6 * x - 3), //
1124 1);
1125 };
1126
1127 Paint paint;
1128 paint.blend_mode = BlendMode::kSourceOver;
1129
1130 // Draw a fancy color wheel for the backdrop.
1131 // https://www.desmos.com/calculator/xw7kafthwd
1132 const int max_dist = 900;
1133 for (int i = 0; i <= 900; i++) {
1134 Radians r(kPhi / k2Pi * i);
1135 Scalar distance = r.radians / std::powf(4.12, 0.0026 * r.radians);
1136 Scalar normalized_distance = static_cast<Scalar>(i) / max_dist;
1137
1138 paint.color =
1139 color_wheel_sampler(r).WithAlpha(1.0f - normalized_distance);
1140 Point position(distance * std::sin(r.radians),
1141 -distance * std::cos(r.radians));
1142
1143 canvas.DrawCircle(position, 9 + normalized_distance * 3, paint);
1144 }
1145 };
1146
1147 std::shared_ptr<Image> color_wheel_image;
1148 Matrix color_wheel_transform;
1149
1150 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1151 // UI state.
1152 static bool cache_the_wheel = true;
1153 static int current_blend_index = 3;
1154 static float dst_alpha = 1;
1155 static float src_alpha = 1;
1156 static Color color0 = Color::Red();
1157 static Color color1 = Color::Green();
1158 static Color color2 = Color::Blue();
1159
1160 if (AiksTest::ImGuiBegin("Controls", nullptr,
1161 ImGuiWindowFlags_AlwaysAutoResize)) {
1162 ImGui::Checkbox("Cache the wheel", &cache_the_wheel);
1163 ImGui::ListBox("Blending mode", &current_blend_index,
1164 blend_modes.blend_mode_names.data(),
1165 blend_modes.blend_mode_names.size());
1166 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
1167 ImGui::ColorEdit4("Color A", reinterpret_cast<float*>(&color0));
1168 ImGui::ColorEdit4("Color B", reinterpret_cast<float*>(&color1));
1169 ImGui::ColorEdit4("Color C", reinterpret_cast<float*>(&color2));
1170 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
1171 ImGui::End();
1172 }
1173
1174 static Point content_scale;
1175 Point new_content_scale = GetContentScale();
1176
1177 if (!cache_the_wheel || new_content_scale != content_scale) {
1178 content_scale = new_content_scale;
1179
1180 // Render the color wheel to an image.
1181
1182 Canvas canvas;
1183 canvas.Scale(content_scale);
1184
1185 canvas.Translate(Vector2(500, 400));
1186 canvas.Scale(Vector2(3, 3));
1187
1188 draw_color_wheel(canvas);
1189 auto color_wheel_picture = canvas.EndRecordingAsPicture();
1190 auto snapshot = color_wheel_picture.Snapshot(renderer);
1191 if (!snapshot.has_value() || !snapshot->texture) {
1192 return std::nullopt;
1193 }
1194 color_wheel_image = std::make_shared<Image>(snapshot->texture);
1195 color_wheel_transform = snapshot->transform;
1196 }
1197
1198 Canvas canvas;
1199
1200 // Blit the color wheel backdrop to the screen with managed alpha.
1201 canvas.SaveLayer({.color = Color::White().WithAlpha(dst_alpha),
1202 .blend_mode = BlendMode::kSource});
1203 {
1204 canvas.DrawPaint({.color = Color::White()});
1205
1206 canvas.Save();
1207 canvas.Transform(color_wheel_transform);
1208 canvas.DrawImage(color_wheel_image, Point(), Paint());
1209 canvas.Restore();
1210 }
1211 canvas.Restore();
1212
1213 canvas.Scale(content_scale);
1214 canvas.Translate(Vector2(500, 400));
1215 canvas.Scale(Vector2(3, 3));
1216
1217 // Draw 3 circles to a subpass and blend it in.
1218 canvas.SaveLayer(
1219 {.color = Color::White().WithAlpha(src_alpha),
1220 .blend_mode = blend_modes.blend_mode_values[current_blend_index]});
1221 {
1222 Paint paint;
1223 paint.blend_mode = BlendMode::kPlus;
1224 const Scalar x = std::sin(k2Pi / 3);
1225 const Scalar y = -std::cos(k2Pi / 3);
1226 paint.color = color0;
1227 canvas.DrawCircle(Point(-x, y) * 45, 65, paint);
1228 paint.color = color1;
1229 canvas.DrawCircle(Point(0, -1) * 45, 65, paint);
1230 paint.color = color2;
1231 canvas.DrawCircle(Point(x, y) * 45, 65, paint);
1232 }
1233 canvas.Restore();
1234
1235 return canvas.EndRecordingAsPicture();
1236 };
1237
1238 ASSERT_TRUE(OpenPlaygroundHere(callback));
1239 }

References impeller::Paint::blend_mode, impeller::testing::BlendModeSelection::blend_mode_names, impeller::testing::BlendModeSelection::blend_mode_values, impeller::Color::Blue(), impeller::Paint::color, impeller::saturated::distance, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawImage(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), GetBlendModeSelection(), impeller::Color::Green(), impeller::AiksPlayground::ImGuiBegin(), impeller::k2Pi, impeller::kPhi, impeller::kPlus, impeller::kSource, impeller::kSourceOver, impeller::Radians::radians, impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), impeller::Picture::Snapshot(), impeller::Canvas::Transform(), impeller::Canvas::Translate(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [119/419]

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

Definition at line 569 of file aiks_unittests.cc.

569 {
570 Canvas canvas;
571
572 // Render a texture directly.
573 {
574 Paint paint;
575 auto image =
576 std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
577 paint.color = Color::Red();
578
579 canvas.Save();
580 canvas.Translate({100, 200, 0});
581 canvas.Scale(Vector2{0.5, 0.5});
582 canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
583 canvas.Restore();
584 }
585
586 // Render an offscreen rendered texture.
587 {
588 Paint red;
589 red.color = Color::Red();
590 Paint green;
591 green.color = Color::Green();
592 Paint blue;
593 blue.color = Color::Blue();
594
595 Paint alpha;
596 alpha.color = Color::Red().WithAlpha(0.5);
597
598 canvas.SaveLayer(alpha);
599
600 canvas.DrawRect(Rect::MakeXYWH(000, 000, 100, 100), red);
601 canvas.DrawRect(Rect::MakeXYWH(020, 020, 100, 100), green);
602 canvas.DrawRect(Rect::MakeXYWH(040, 040, 100, 100), blue);
603
604 canvas.Restore();
605 }
606
607 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
608 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::TPoint< Scalar >::MakeXY(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), impeller::Canvas::Translate(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [120/419]

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

Definition at line 3334 of file aiks_unittests.cc.

3334 {
3335 Canvas canvas; // Depth 1 (base pass)
3336 canvas.DrawRRect(Rect::MakeLTRB(0, 0, 100, 100), {10, 10}, {}); // Depth 2
3337 canvas.Save();
3338 {
3339 canvas.ClipRRect(Rect::MakeLTRB(0, 0, 50, 50), {10, 10}, {}); // Depth 4
3340 canvas.SaveLayer({}); // Depth 4
3341 {
3342 canvas.DrawRRect(Rect::MakeLTRB(0, 0, 50, 50), {10, 10}, {}); // Depth 3
3343 }
3344 canvas.Restore(); // Restore the savelayer.
3345 }
3346 canvas.Restore(); // Depth 5 -- this will no longer append a restore entity
3347 // once we switch to the clip depth approach.
3348
3349 auto picture = canvas.EndRecordingAsPicture();
3350
3351 std::vector<uint32_t> expected = {
3352 2, // DrawRRect
3353 4, // ClipRRect -- Has a depth value equal to the max depth of all the
3354 // content it affect. In this case, the SaveLayer and all
3355 // its contents are affected.
3356 4, // SaveLayer -- The SaveLayer is drawn to the parent pass after its
3357 // contents are rendered, so it should have a depth value
3358 // greater than all its contents.
3359 3, // DrawRRect
3360 5, // Restore (no longer necessary when clipping on the depth buffer)
3361 };
3362
3363 std::vector<uint32_t> actual;
3364
3365 picture.pass->IterateAllElements([&](EntityPass::Element& element) -> bool {
3366 if (auto* subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
3367 actual.push_back(subpass->get()->GetNewClipDepth());
3368 }
3369 if (Entity* entity = std::get_if<Entity>(&element)) {
3370 actual.push_back(entity->GetNewClipDepth());
3371 }
3372 return true;
3373 });
3374
3375 ASSERT_EQ(actual.size(), expected.size());
3376 for (size_t i = 0; i < expected.size(); i++) {
3377 EXPECT_EQ(expected[i], actual[i]) << "Index: " << i;
3378 }
3379 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Picture::pass, impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [121/419]

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

Definition at line 1708 of file aiks_unittests.cc.

1708 {
1709 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1710 Canvas canvas;
1711 canvas.Scale(GetContentScale());
1712
1713 Paint alpha;
1714 alpha.color = Color::Red().WithAlpha(0.5);
1715
1716 auto current = Point{25, 25};
1717 const auto offset = Point{25, 25};
1718 const auto size = Size(100, 100);
1719
1720 static PlaygroundPoint point_a(Point(40, 40), 10, Color::White());
1721 static PlaygroundPoint point_b(Point(160, 160), 10, Color::White());
1722 auto [b0, b1] = DrawPlaygroundLine(point_a, point_b);
1723 auto bounds = Rect::MakeLTRB(b0.x, b0.y, b1.x, b1.y);
1724
1725 canvas.DrawRect(bounds, Paint{.color = Color::Yellow(),
1726 .stroke_width = 5.0f,
1727 .style = Paint::Style::kStroke});
1728
1729 canvas.SaveLayer(alpha, bounds);
1730
1731 canvas.DrawRect(Rect::MakeOriginSize(current, size),
1732 Paint{.color = Color::Red()});
1733 canvas.DrawRect(Rect::MakeOriginSize(current += offset, size),
1734 Paint{.color = Color::Green()});
1735 canvas.DrawRect(Rect::MakeOriginSize(current += offset, size),
1736 Paint{.color = Color::Blue()});
1737
1738 canvas.Restore();
1739
1740 return canvas.EndRecordingAsPicture();
1741 };
1742
1743 ASSERT_TRUE(OpenPlaygroundHere(callback));
1744 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::DrawPlaygroundLine(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Paint::kStroke, impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeOriginSize(), offset, impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), impeller::Color::White(), impeller::Color::WithAlpha(), and impeller::Color::Yellow().

## ◆ TEST_P() [122/419]

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

Definition at line 1013 of file aiks_unittests.cc.

1013 {
1014 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
1015 Color{0.1294, 0.5882, 0.9529, 1.0}};
1016 std::vector<Scalar> stops = {0.0, 1.0};
1017
1018 Paint paint = {
1019 .color_source = ColorSource::MakeLinearGradient(
1020 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
1021 Entity::TileMode::kRepeat, Matrix::MakeScale(Vector3(0.3, 0.3, 0.3))),
1022 .blend_mode = BlendMode::kLighten,
1023 };
1024
1025 Canvas canvas;
1026 canvas.DrawPaint({.color = Color::Blue()});
1027 canvas.Scale(Vector2(2, 2));
1028 canvas.ClipRect(Rect::MakeLTRB(0, 0, 200, 200));
1029 canvas.DrawCircle({100, 100}, 100, paint);
1030 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1031 }

References impeller::Color::Blue(), impeller::Canvas::ClipRect(), impeller::Paint::color_source, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kLighten, impeller::Entity::kRepeat, impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), and impeller::Canvas::Scale().

## ◆ TEST_P() [123/419]

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

Definition at line 2840 of file aiks_unittests.cc.

2840 {
2841 // Draws the image as four squares stiched together.
2842 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
2843 auto size = atlas->GetSize();
2844 auto image = std::make_shared<Image>(atlas);
2845 // Divide image into four quadrants.
2846 Scalar half_width = size.width / 2;
2847 Scalar half_height = size.height / 2;
2848 std::vector<Rect> texture_coordinates = {
2849 Rect::MakeLTRB(0, 0, half_width, half_height),
2850 Rect::MakeLTRB(half_width, 0, size.width, half_height),
2851 Rect::MakeLTRB(0, half_height, half_width, size.height),
2852 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
2853 // Position quadrants adjacent to eachother.
2854 std::vector<Matrix> transforms = {
2855 Matrix::MakeTranslation({0, 0, 0}),
2856 Matrix::MakeTranslation({half_width, 0, 0}),
2857 Matrix::MakeTranslation({0, half_height, 0}),
2858 Matrix::MakeTranslation({half_width, half_height, 0})};
2859
2860 Paint paint;
2861
2862 Canvas canvas;
2863 canvas.Scale({0.25, 0.25, 1.0});
2864 canvas.DrawAtlas(image, transforms, texture_coordinates, {},
2865 BlendMode::kModulate, {}, std::nullopt, paint);
2866
2867 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2868 }

References impeller::Canvas::DrawAtlas(), impeller::Canvas::EndRecordingAsPicture(), impeller::kModulate, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), and impeller::Canvas::Scale().

## ◆ TEST_P() [124/419]

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

Definition at line 2807 of file aiks_unittests.cc.

2807 {
2808 // Draws the image as four squares stiched together.
2809 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
2810 auto size = atlas->GetSize();
2811 auto image = std::make_shared<Image>(atlas);
2812 // Divide image into four quadrants.
2813 Scalar half_width = size.width / 2;
2814 Scalar half_height = size.height / 2;
2815 std::vector<Rect> texture_coordinates = {
2816 Rect::MakeLTRB(0, 0, half_width, half_height),
2817 Rect::MakeLTRB(half_width, 0, size.width, half_height),
2818 Rect::MakeLTRB(0, half_height, half_width, size.height),
2819 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
2820 // Position quadrants adjacent to eachother.
2821 std::vector<Matrix> transforms = {
2822 Matrix::MakeTranslation({0, 0, 0}),
2823 Matrix::MakeTranslation({half_width, 0, 0}),
2824 Matrix::MakeTranslation({0, half_height, 0}),
2825 Matrix::MakeTranslation({half_width, half_height, 0})};
2826 std::vector<Color> colors = {Color::Red(), Color::Green(), Color::Blue(),
2827 Color::Yellow()};
2828
2829 Paint paint;
2830
2831 Canvas canvas;
2832 canvas.Scale({0.25, 0.25, 1.0});
2833 canvas.DrawAtlas(image, transforms, texture_coordinates, colors,
2834 BlendMode::kModulate, {}, std::nullopt, paint);
2835
2836 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2837 }

References impeller::Color::Blue(), impeller::Canvas::DrawAtlas(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::kModulate, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Canvas::Scale(), and impeller::Color::Yellow().

## ◆ TEST_P() [125/419]

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

Definition at line 250 of file aiks_path_unittests.cc.

250 {
251 Canvas canvas;
252 canvas.Scale(GetContentScale());
253 Paint paint;
254 paint.color = Color::Blue();
255 paint.stroke_width = 10;
256
257 auto draw = [&canvas](Paint& paint) {
258 for (auto cap : {Cap::kButt, Cap::kSquare, Cap::kRound}) {
259 paint.stroke_cap = cap;
260 Point origin = {100, 100};
261 Point p0 = {50, 0};
262 Point p1 = {150, 0};
263 canvas.DrawLine({150, 100}, {250, 100}, paint);
264 for (int d = 15; d < 90; d += 15) {
265 Matrix m = Matrix::MakeRotationZ(Degrees(d));
266 canvas.DrawLine(origin + m * p0, origin + m * p1, paint);
267 }
268 canvas.DrawLine({100, 150}, {100, 250}, paint);
269 canvas.DrawCircle({origin}, 35, paint);
270
271 canvas.DrawLine({250, 250}, {250, 250}, paint);
272
273 canvas.Translate({250, 0});
274 }
275 canvas.Translate({-750, 250});
276 };
277
278 std::vector<Color> colors = {
279 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
280 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
281 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
282 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
283 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
284 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
285 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
286 std::vector<Scalar> stops = {
287 0.0,
288 (1.0 / 6.0) * 1,
289 (1.0 / 6.0) * 2,
290 (1.0 / 6.0) * 3,
291 (1.0 / 6.0) * 4,
292 (1.0 / 6.0) * 5,
293 1.0,
294 };
295
296 auto texture = CreateTextureForFixture("airplane.jpg",
297 /*enable_mipmapping=*/true);
298
299 draw(paint);
300
301 paint.color_source = ColorSource::MakeRadialGradient(
302 {100, 100}, 200, std::move(colors), std::move(stops),
303 Entity::TileMode::kMirror, {});
304 draw(paint);
305
306 paint.color_source = ColorSource::MakeImage(
307 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
308 Matrix::MakeTranslation({-150, 75}));
309 draw(paint);
310
311 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
312 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Paint::color_source, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawLine(), impeller::Canvas::EndRecordingAsPicture(), impeller::kButt, impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::kRound, impeller::kSquare, impeller::ColorSource::MakeImage(), impeller::ColorSource::MakeRadialGradient(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Scale(), impeller::Paint::stroke_cap, impeller::Paint::stroke_width, and impeller::Canvas::Translate().

## ◆ TEST_P() [126/419]

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

Definition at line 1964 of file aiks_unittests.cc.

1964 {
1965 Canvas canvas;
1966 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
1967 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
1968 .blend_mode = BlendMode::kSourceOver});
1969
1970 Picture picture = canvas.EndRecordingAsPicture();
1971 auto expected = Color::Red().Blend(Color::CornflowerBlue().WithAlpha(0.75),
1972 BlendMode::kSourceOver);
1973 ASSERT_EQ(picture.pass->GetClearColor(), expected);
1974
1975 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1976 std::shared_ptr<Context> real_context = GetContext();
1977 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1978 AiksContext renderer(mock_context, nullptr);
1979 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1980
1981 ASSERT_EQ(spy->render_passes_.size(), 1llu);
1982 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1983 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
1984 }

References impeller::Color::Blend(), impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSource, impeller::kSourceOver, impeller::Picture::pass, impeller::Color::Red(), impeller::Picture::ToImage(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [127/419]

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

Definition at line 2747 of file aiks_unittests.cc.

2747 {
2748 auto runtime_stages = OpenAssetAsRuntimeStage("gradient.frag.iplr");
2749 auto runtime_stage =
2750 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2751 ASSERT_TRUE(runtime_stage);
2752 ASSERT_TRUE(runtime_stage->IsDirty());
2753
2754 struct FragUniforms {
2755 Size size;
2756 } frag_uniforms = {.size = Size::MakeWH(400, 400)};
2757 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2758 uniform_data->resize(sizeof(FragUniforms));
2759 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2760
2761 std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
2762
2763 Paint paint;
2764 paint.color_source = ColorSource::MakeRuntimeEffect(
2765 runtime_stage, uniform_data, texture_inputs);
2766
2767 Canvas canvas;
2768 canvas.Save();
2769 canvas.Scale(GetContentScale());
2770 canvas.DrawPaint(paint);
2771 canvas.Restore();
2772
2773 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2774 }

References impeller::Paint::color_source, impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::ColorSource::MakeRuntimeEffect(), impeller::TSize< Scalar >::MakeWH(), impeller::PlaygroundBackendToRuntimeStageBackend(), impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::Canvas::Scale().

## ◆ TEST_P() [128/419]

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

Definition at line 996 of file aiks_unittests.cc.

996 {
997 Paint filtered = {
998 .color = Color::Black(),
999 .mask_blur_descriptor =
1000 Paint::MaskBlurDescriptor{
1001 .style = FilterContents::BlurStyle::kNormal,
1002 .sigma = Sigma(60),
1003 },
1004 };
1005
1006 Canvas canvas;
1007 canvas.DrawPaint({.color = Color::White()});
1008 canvas.DrawCircle({300, 300}, 200, filtered);
1009 canvas.DrawPaint({.color = Color::Green(), .blend_mode = BlendMode::kScreen});
1010 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1011 }

References impeller::Color::Black(), impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kNormal, impeller::kScreen, impeller::Paint::MaskBlurDescriptor::style, and impeller::Color::White().

## ◆ TEST_P() [129/419]

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

Definition at line 2011 of file aiks_unittests.cc.

2011 {
2012 Canvas canvas;
2013 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
2014 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
2015 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
2016 {.color = Color::CornflowerBlue().WithAlpha(0.75),
2017 .blend_mode = BlendMode::kSourceOver});
2018
2019 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2020 Picture picture = canvas.EndRecordingAsPicture();
2021 std::shared_ptr<Context> real_context = GetContext();
2022 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2023 AiksContext renderer(mock_context, nullptr);
2024 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
2025
2026 ASSERT_EQ(spy->render_passes_.size(), 1llu);
2027 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2028 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
2029 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSource, impeller::kSourceOver, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Picture::ToImage(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [130/419]

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

Definition at line 2071 of file aiks_unittests.cc.

2071 {
2072 Canvas canvas;
2073 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
2074 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
2075 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
2076 {.color = Color::CornflowerBlue().WithAlpha(0.75),
2077 .blend_mode = BlendMode::kSourceOver});
2078
2079 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2080 Picture picture = canvas.EndRecordingAsPicture();
2081 std::shared_ptr<Context> real_context = GetContext();
2082 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2083 AiksContext renderer(mock_context, nullptr);
2084 std::shared_ptr<Image> image = picture.ToImage(renderer, {301, 301});
2085
2086 ASSERT_EQ(spy->render_passes_.size(), 1llu);
2087 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2088 ASSERT_EQ(render_pass->GetCommands().size(), 2llu);
2089 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSource, impeller::kSourceOver, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Picture::ToImage(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [131/419]

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

Definition at line 2051 of file aiks_unittests.cc.

2051 {
2052 Canvas canvas;
2053 canvas.Translate(Vector3(150.0, 150.0, 0.0));
2054 canvas.Rotate(Degrees(45.0));
2055 canvas.Translate(Vector3(-150.0, -150.0, 0.0));
2056 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
2057 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
2058
2059 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2060 Picture picture = canvas.EndRecordingAsPicture();
2061 std::shared_ptr<Context> real_context = GetContext();
2062 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2063 AiksContext renderer(mock_context, nullptr);
2064 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
2065
2066 ASSERT_EQ(spy->render_passes_.size(), 1llu);
2067 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2068 ASSERT_EQ(render_pass->GetCommands().size(), 1llu);
2069 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSource, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Rotate(), impeller::Picture::ToImage(), and impeller::Canvas::Translate().

## ◆ TEST_P() [132/419]

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

Definition at line 2031 of file aiks_unittests.cc.

2031 {
2032 Canvas canvas;
2033 canvas.DrawRRect(Rect::MakeXYWH(0, 0, 300, 300), {5.0, 5.0},
2034 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
2035 canvas.DrawRRect(Rect::MakeXYWH(0, 0, 300, 300), {5.0, 5.0},
2036 {.color = Color::CornflowerBlue().WithAlpha(0.75),
2037 .blend_mode = BlendMode::kSourceOver});
2038
2039 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2040 Picture picture = canvas.EndRecordingAsPicture();
2041 std::shared_ptr<Context> real_context = GetContext();
2042 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2043 AiksContext renderer(mock_context, nullptr);
2044 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
2045
2046 ASSERT_EQ(spy->render_passes_.size(), 1llu);
2047 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2048 ASSERT_EQ(render_pass->GetCommands().size(), 2llu);
2049 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSource, impeller::kSourceOver, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Picture::ToImage(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [133/419]

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

Definition at line 314 of file aiks_path_unittests.cc.

314 {
315 Canvas canvas;
316 Paint paint;
317 paint.color = Color::Red();
318 paint.style = Paint::Style::kStroke;
319 paint.stroke_width = 10;
320
321 canvas.Translate({100, 100});
322 canvas.DrawPath(
323 PathBuilder{}.AddRect(Rect::MakeSize(Size{100, 100})).TakePath(),
324 {paint});
325
326 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
327 }

References impeller::PathBuilder::AddRect(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, impeller::TRect< Scalar >::MakeSize(), impeller::Color::Red(), impeller::Paint::stroke_width, impeller::Paint::style, and impeller::Canvas::Translate().

## ◆ TEST_P() [134/419]

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

Definition at line 329 of file aiks_path_unittests.cc.

329 {
330 Canvas canvas;
331 Paint paint;
332 paint.color = Color::Red();
333 paint.style = Paint::Style::kStroke;
334 paint.stroke_width = 10;
335 paint.stroke_join = Join::kBevel;
336
337 canvas.Translate({100, 100});
338 canvas.DrawPath(
339 PathBuilder{}.AddRect(Rect::MakeSize(Size{100, 100})).TakePath(),
340 {paint});
341
342 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
343 }

References impeller::PathBuilder::AddRect(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::kBevel, impeller::Paint::kStroke, impeller::TRect< Scalar >::MakeSize(), impeller::Color::Red(), impeller::Paint::stroke_join, impeller::Paint::stroke_width, impeller::Paint::style, and impeller::Canvas::Translate().

## ◆ TEST_P() [135/419]

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

Definition at line 2998 of file aiks_unittests.cc.

2998 {
2999 Canvas canvas;
3000 canvas.Transform(Matrix(1.0, 0.0, 0.0, 0.0, //
3001 0.0, 1.0, 0.0, 0.0, //
3002 0.0, 0.0, 1.0, 0.01, //
3003 0.0, 0.0, 0.0, 1.0) * //
3004 Matrix::MakeRotationY({Degrees{10}}));
3005
3006 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), canvas, "Hello world",
3007 "Roboto-Regular.ttf"));
3008
3009 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3010 }

References impeller::Canvas::EndRecordingAsPicture(), impeller::Matrix::MakeRotationY(), RenderTextInCanvasSkia(), and impeller::Canvas::Transform().

## ◆ TEST_P() [136/419]

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

Definition at line 3012 of file aiks_unittests.cc.

3012 {
3013 Canvas canvas;
3014 Paint save_paint;
3015 canvas.SaveLayer(save_paint);
3016 canvas.Transform(Matrix(1.0, 0.0, 0.0, 0.0, //
3017 0.0, 1.0, 0.0, 0.0, //
3018 0.0, 0.0, 1.0, 0.01, //
3019 0.0, 0.0, 0.0, 1.0) * //
3020 Matrix::MakeRotationY({Degrees{10}}));
3021
3022 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), canvas, "Hello world",
3023 "Roboto-Regular.ttf"));
3024 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3025 }

References impeller::Canvas::EndRecordingAsPicture(), impeller::Matrix::MakeRotationY(), RenderTextInCanvasSkia(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Transform().

## ◆ TEST_P() [137/419]

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

Definition at line 3244 of file aiks_unittests.cc.

3244 {
3245 Canvas canvas;
3246 canvas.Scale(GetContentScale());
3247 canvas.DrawPaint(Paint{.color = Color::Red()});
3248 canvas.ClipRect(Rect::MakeXYWH(100, 100, 200, 200));
3249 canvas.SaveLayer(Paint{.color = Color::Blue()});
3250 canvas.Restore();
3251 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3252 }

References impeller::Color::Blue(), impeller::Canvas::ClipRect(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Scale().

## ◆ TEST_P() [138/419]

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

Definition at line 3254 of file aiks_unittests.cc.

3254 {
3255 Canvas canvas;
3256 canvas.Scale(GetContentScale());
3257 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
3258 canvas.DrawImage(image, {10, 10}, {});
3259 canvas.ClipRect(Rect::MakeXYWH(100, 100, 200, 200));
3260 canvas.SaveLayer(Paint{.blend_mode = BlendMode::kClear});
3261 canvas.Restore();
3262 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3263 }

References impeller::Paint::blend_mode, impeller::Canvas::ClipRect(), impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::kClear, impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Scale().

## ◆ TEST_P() [139/419]

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

Definition at line 1280 of file aiks_unittests.cc.

1280 {
1281 Canvas canvas;
1282 canvas.Scale(GetContentScale());
1283 Paint paint;
1284 const int color_count = 3;
1285 Color colors[color_count] = {
1286 Color::Blue(),
1287 Color::Green(),
1288 Color::Crimson(),
1289 };
1290
1291 paint.color = Color::White();
1292 canvas.DrawPaint(paint);
1293
1294 int c_index = 0;
1295 int radius = 600;
1296 while (radius > 0) {
1297 paint.color = colors[(c_index++) % color_count];
1298 canvas.DrawCircle({10, 10}, radius, paint);
1299 if (radius > 30) {
1300 radius -= 10;
1301 } else {
1302 radius -= 2;
1303 }
1304 }
1305
1306 std::vector<Color> gradient_colors = {
1307 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1308 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1309 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1310 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1311 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1312 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1313 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1314 std::vector<Scalar> stops = {
1315 0.0,
1316 (1.0 / 6.0) * 1,
1317 (1.0 / 6.0) * 2,
1318 (1.0 / 6.0) * 3,
1319 (1.0 / 6.0) * 4,
1320 (1.0 / 6.0) * 5,
1321 1.0,
1322 };
1323 auto texture = CreateTextureForFixture("airplane.jpg",
1324 /*enable_mipmapping=*/true);
1325
1326 paint.color_source = ColorSource::MakeRadialGradient(
1327 {500, 600}, 75, std::move(gradient_colors), std::move(stops),
1328 Entity::TileMode::kMirror, {});
1329 canvas.DrawCircle({500, 600}, 100, paint);
1330
1331 paint.color_source = ColorSource::MakeImage(
1332 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1333 Matrix::MakeTranslation({700, 200}));
1334 canvas.DrawCircle({800, 300}, 100, paint);
1335
1336 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1337 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Paint::color_source, impeller::Color::Crimson(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeImage(), impeller::ColorSource::MakeRadialGradient(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Scale(), and impeller::Color::White().

## ◆ TEST_P() [140/419]

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

Definition at line 1403 of file aiks_unittests.cc.

1403 {
1404 Canvas canvas;
1405 canvas.Scale(GetContentScale());
1406 Paint paint;
1407 const int color_count = 3;
1408 Color colors[color_count] = {
1409 Color::Blue(),
1410 Color::Green(),
1411 Color::Crimson(),
1412 };
1413
1414 paint.color = Color::White();
1415 canvas.DrawPaint(paint);
1416
1417 int c_index = 0;
1418 int long_radius = 600;
1419 int short_radius = 600;
1420 while (long_radius > 0 && short_radius > 0) {
1421 paint.color = colors[(c_index++) % color_count];
1422 canvas.DrawOval(Rect::MakeXYWH(10 - long_radius, 10 - short_radius,
1423 long_radius * 2, short_radius * 2),
1424 paint);
1425 canvas.DrawOval(Rect::MakeXYWH(1000 - short_radius, 750 - long_radius,
1426 short_radius * 2, long_radius * 2),
1427 paint);
1428 if (short_radius > 30) {
1429 short_radius -= 10;
1430 long_radius -= 5;
1431 } else {
1432 short_radius -= 2;
1433 long_radius -= 1;
1434 }
1435 }
1436
1437 std::vector<Color> gradient_colors = {
1438 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1439 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1440 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1441 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1442 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1443 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1444 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1445 std::vector<Scalar> stops = {
1446 0.0,
1447 (1.0 / 6.0) * 1,
1448 (1.0 / 6.0) * 2,
1449 (1.0 / 6.0) * 3,
1450 (1.0 / 6.0) * 4,
1451 (1.0 / 6.0) * 5,
1452 1.0,
1453 };
1454 auto texture = CreateTextureForFixture("airplane.jpg",
1455 /*enable_mipmapping=*/true);
1456
1457 paint.color = Color::White().WithAlpha(0.5);
1458
1459 paint.color_source = ColorSource::MakeRadialGradient(
1460 {300, 650}, 75, std::move(gradient_colors), std::move(stops),
1461 Entity::TileMode::kMirror, {});
1462 canvas.DrawOval(Rect::MakeXYWH(200, 625, 200, 50), paint);
1463 canvas.DrawOval(Rect::MakeXYWH(275, 550, 50, 200), paint);
1464
1465 paint.color_source = ColorSource::MakeImage(
1466 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1467 Matrix::MakeTranslation({610, 15}));
1468 canvas.DrawOval(Rect::MakeXYWH(610, 90, 200, 50), paint);
1469 canvas.DrawOval(Rect::MakeXYWH(685, 15, 50, 200), paint);
1470
1471 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1472 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Paint::color_source, impeller::Color::Crimson(), impeller::Canvas::DrawOval(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeImage(), impeller::ColorSource::MakeRadialGradient(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Scale(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [141/419]

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

Definition at line 1618 of file aiks_unittests.cc.

1618 {
1619 Canvas canvas;
1620 canvas.Scale(GetContentScale());
1621 Paint paint;
1622 const int color_count = 3;
1623 Color colors[color_count] = {
1624 Color::Blue(),
1625 Color::Green(),
1626 Color::Crimson(),
1627 };
1628
1629 paint.color = Color::White();
1630 canvas.DrawPaint(paint);
1631
1632 auto draw_rrect_as_path = [&canvas](const Rect& rect, const Size& radii,
1633 const Paint& paint) {
1634 PathBuilder builder = PathBuilder();
1635 builder.AddRoundedRect(rect, radii);
1636 canvas.DrawPath(builder.TakePath(), paint);
1637 };
1638
1639 int c_index = 0;
1640 for (int i = 0; i < 4; i++) {
1641 for (int j = 0; j < 4; j++) {
1642 paint.color = colors[(c_index++) % color_count];
1643 draw_rrect_as_path(Rect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1644 Size(i * 5 + 10, j * 5 + 10), paint);
1645 }
1646 }
1647 paint.color = colors[(c_index++) % color_count];
1648 draw_rrect_as_path(Rect::MakeXYWH(10, 420, 380, 80), Size(40, 40), paint);
1649 paint.color = colors[(c_index++) % color_count];
1650 draw_rrect_as_path(Rect::MakeXYWH(410, 20, 80, 380), Size(40, 40), paint);
1651
1652 std::vector<Color> gradient_colors = {
1653 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1654 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1655 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1656 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1657 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1658 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1659 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1660 std::vector<Scalar> stops = {
1661 0.0,
1662 (1.0 / 6.0) * 1,
1663 (1.0 / 6.0) * 2,
1664 (1.0 / 6.0) * 3,
1665 (1.0 / 6.0) * 4,
1666 (1.0 / 6.0) * 5,
1667 1.0,
1668 };
1669 auto texture = CreateTextureForFixture("airplane.jpg",
1670 /*enable_mipmapping=*/true);
1671
1672 paint.color = Color::White().WithAlpha(0.1);
1673 paint.color_source = ColorSource::MakeRadialGradient(
1674 {550, 550}, 75, gradient_colors, stops, Entity::TileMode::kMirror, {});
1675 for (int i = 1; i <= 10; i++) {
1676 int j = 11 - i;
1677 draw_rrect_as_path(Rect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1678 550 + i * 20, 550 + j * 20),
1679 Size(i * 10, j * 10), paint);
1680 }
1681 paint.color = Color::White().WithAlpha(0.5);
1682 paint.color_source = ColorSource::MakeRadialGradient(
1683 {200, 650}, 75, std::move(gradient_colors), std::move(stops),
1684 Entity::TileMode::kMirror, {});
1685 draw_rrect_as_path(Rect::MakeLTRB(100, 610, 300, 690), Size(40, 40), paint);
1686 draw_rrect_as_path(Rect::MakeLTRB(160, 550, 240, 750), Size(40, 40), paint);
1687
1688 paint.color = Color::White().WithAlpha(0.1);
1689 paint.color_source = ColorSource::MakeImage(
1690 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1691 Matrix::MakeTranslation({520, 20}));
1692 for (int i = 1; i <= 10; i++) {
1693 int j = 11 - i;
1694 draw_rrect_as_path(Rect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1695 720 + i * 20, 220 + j * 20),
1696 Size(i * 10, j * 10), paint);
1697 }
1698 paint.color = Color::White().WithAlpha(0.5);
1699 paint.color_source = ColorSource::MakeImage(
1700 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1701 Matrix::MakeTranslation({800, 300}));
1702 draw_rrect_as_path(Rect::MakeLTRB(800, 410, 1000, 490), Size(40, 40), paint);
1703 draw_rrect_as_path(Rect::MakeLTRB(860, 350, 940, 550), Size(40, 40), paint);
1704
1705 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1706 }

References impeller::PathBuilder::AddRoundedRect(), impeller::Color::Blue(), impeller::Paint::color, impeller::Paint::color_source, impeller::Color::Crimson(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeImage(), impeller::TRect< Scalar >::MakeLTRB(), impeller::ColorSource::MakeRadialGradient(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Scale(), impeller::PathBuilder::TakePath(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [142/419]

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

Definition at line 1474 of file aiks_unittests.cc.

1474 {
1475 Canvas canvas;
1476 canvas.Scale(GetContentScale());
1477 Paint paint;
1478 const int color_count = 3;
1479 Color colors[color_count] = {
1480 Color::Blue(),
1481 Color::Green(),
1482 Color::Crimson(),
1483 };
1484
1485 paint.color = Color::White();
1486 canvas.DrawPaint(paint);
1487
1488 int c_index = 0;
1489 for (int i = 0; i < 4; i++) {
1490 for (int j = 0; j < 4; j++) {
1491 paint.color = colors[(c_index++) % color_count];
1492 canvas.DrawRRect(Rect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1493 Size(i * 5 + 10, j * 5 + 10), paint);
1494 }
1495 }
1496 paint.color = colors[(c_index++) % color_count];
1497 canvas.DrawRRect(Rect::MakeXYWH(10, 420, 380, 80), Size(40, 40), paint);
1498 paint.color = colors[(c_index++) % color_count];
1499 canvas.DrawRRect(Rect::MakeXYWH(410, 20, 80, 380), Size(40, 40), paint);
1500
1501 std::vector<Color> gradient_colors = {
1502 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1503 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1504 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1505 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1506 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1507 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1508 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1509 std::vector<Scalar> stops = {
1510 0.0,
1511 (1.0 / 6.0) * 1,
1512 (1.0 / 6.0) * 2,
1513 (1.0 / 6.0) * 3,
1514 (1.0 / 6.0) * 4,
1515 (1.0 / 6.0) * 5,
1516 1.0,
1517 };
1518 auto texture = CreateTextureForFixture("airplane.jpg",
1519 /*enable_mipmapping=*/true);
1520
1521 paint.color = Color::White().WithAlpha(0.1);
1522 paint.color_source = ColorSource::MakeRadialGradient(
1523 {550, 550}, 75, gradient_colors, stops, Entity::TileMode::kMirror, {});
1524 for (int i = 1; i <= 10; i++) {
1525 int j = 11 - i;
1526 canvas.DrawRRect(Rect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1527 550 + i * 20, 550 + j * 20),
1528 Size(i * 10, j * 10), paint);
1529 }
1530 paint.color = Color::White().WithAlpha(0.5);
1531 paint.color_source = ColorSource::MakeRadialGradient(
1532 {200, 650}, 75, std::move(gradient_colors), std::move(stops),
1533 Entity::TileMode::kMirror, {});
1534 canvas.DrawRRect(Rect::MakeLTRB(100, 610, 300, 690), Size(40, 40), paint);
1535 canvas.DrawRRect(Rect::MakeLTRB(160, 550, 240, 750), Size(40, 40), paint);
1536
1537 paint.color = Color::White().WithAlpha(0.1);
1538 paint.color_source = ColorSource::MakeImage(
1539 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1540 Matrix::MakeTranslation({520, 20}));
1541 for (int i = 1; i <= 10; i++) {
1542 int j = 11 - i;
1543 canvas.DrawRRect(Rect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1544 720 + i * 20, 220 + j * 20),
1545 Size(i * 10, j * 10), paint);
1546 }
1547 paint.color = Color::White().WithAlpha(0.5);
1548 paint.color_source = ColorSource::MakeImage(
1549 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1550 Matrix::MakeTranslation({800, 300}));
1551 canvas.DrawRRect(Rect::MakeLTRB(800, 410, 1000, 490), Size(40, 40), paint);
1552 canvas.DrawRRect(Rect::MakeLTRB(860, 350, 940, 550), Size(40, 40), paint);
1553
1554 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1555 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Paint::color_source, impeller::Color::Crimson(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeImage(), impeller::TRect< Scalar >::MakeLTRB(), impeller::ColorSource::MakeRadialGradient(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Scale(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [143/419]

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

Definition at line 2169 of file aiks_unittests.cc.

2169 {
2170 Canvas canvas;
2171
2172 canvas.SaveLayer({
2173 .color_filter =
2174 ColorFilter::MakeBlend(BlendMode::kColorDodge, Color::Red()),
2175 });
2176
2177 canvas.Translate({500, 300, 0});
2178 canvas.Rotate(Radians(2 * kPi / 3));
2179 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
2180
2181 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2182 }

References impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kColorDodge, impeller::kPi, impeller::ColorFilter::MakeBlend(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Rotate(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [144/419]

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

Definition at line 1008 of file aiks_blur_unittests.cc.

1008 {
1009 size_t blur_required_mip_count =
1010 GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4;
1011
1012 Canvas canvas;
1013 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
1014 canvas.SaveLayer({}, std::nullopt,
1015 ImageFilter::MakeBlur(Sigma(3), Sigma(3),
1016 FilterContents::BlurStyle::kNormal,
1017 Entity::TileMode::kClamp));
1018 canvas.Restore();
1019
1020 Picture picture = canvas.EndRecordingAsPicture();
1021 std::shared_ptr<RenderTargetCache> cache =
1022 std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
1023 AiksContext aiks_context(GetContext(), nullptr, cache);
1024 picture.ToImage(aiks_context, {100, 100});
1025
1026 size_t max_mip_count = 0;
1027 for (auto it = cache->GetRenderTargetDataBegin();
1028 it != cache->GetRenderTargetDataEnd(); ++it) {
1029 max_mip_count = std::max(it->config.mip_count, max_mip_count);
1030 }
1031 EXPECT_EQ(max_mip_count, blur_required_mip_count);
1032 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kOpenGLES, impeller::ImageFilter::MakeBlur(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Picture::ToImage().

## ◆ TEST_P() [145/419]

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

Definition at line 714 of file aiks_blur_unittests.cc.

714 {
715 // This test is for checking out how stable rendering is when content is
716 // translated underneath a blur. Animating under a blur can cause
717 // *shimmering* to happen as a result of pixel alignment.
718 // See also: https://github.com/flutter/flutter/issues/140193
719 auto boston = std::make_shared<Image>(
720 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true));
721 ASSERT_TRUE(boston);
722 int64_t count = 0;
723 Scalar sigma = 20.0;
724 Scalar freq = 0.1;
725 Scalar amp = 50.0;
726 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
727 if (AiksTest::ImGuiBegin("Controls", nullptr,
728 ImGuiWindowFlags_AlwaysAutoResize)) {
729 ImGui::SliderFloat("Sigma", &sigma, 0, 200);
730 ImGui::SliderFloat("Frequency", &freq, 0.01, 2.0);
731 ImGui::SliderFloat("Amplitude", &amp, 1, 100);
732 ImGui::End();
733 }
734
735 Canvas canvas;
736 canvas.Scale(GetContentScale());
737 Scalar y = amp * sin(freq * 2.0 * M_PI * count / 60);
738 canvas.DrawImage(boston,
739 Point(1024 / 2 - boston->GetSize().width / 2,
740 (768 / 2 - boston->GetSize().height / 2) + y),
741 {});
742 static PlaygroundPoint point_a(Point(100, 100), 20, Color::Red());
743 static PlaygroundPoint point_b(Point(900, 700), 20, Color::Red());
744 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
745 canvas.ClipRect(
746 Rect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
747 canvas.ClipRect(Rect::MakeLTRB(100, 100, 900, 700));
748 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
749 ImageFilter::MakeBlur(Sigma(sigma), Sigma(sigma),
750 FilterContents::BlurStyle::kNormal,
751 Entity::TileMode::kClamp));
752 count += 1;
753 return canvas.EndRecordingAsPicture();
754 };
755 ASSERT_TRUE(OpenPlaygroundHere(callback));
756 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawImage(), impeller::DrawPlaygroundLine(), impeller::Canvas::EndRecordingAsPicture(), impeller::AiksPlayground::ImGuiBegin(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Color::Red(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Scale().

## ◆ TEST_P() [146/419]

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

Definition at line 469 of file aiks_blur_unittests.cc.

469 {
470 Canvas canvas;
471
472 canvas.Scale(GetContentScale());
473 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
474 canvas.DrawImageRect(
475 std::make_shared<Image>(boston),
476 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
477 Rect::MakeLTRB(0, 0, GetWindowSize().width, 100), Paint{});
478 canvas.DrawRRect(Rect::MakeLTRB(0, 110, GetWindowSize().width, 210),
479 Size(10, 10), Paint{.color = Color::Magenta()});
480 canvas.ClipRect(Rect::MakeLTRB(0, 50, GetWindowSize().width, 150));
481 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
482 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
483 FilterContents::BlurStyle::kNormal,
484 Entity::TileMode::kClamp));
485 canvas.Restore();
486 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
487 }

References impeller::Canvas::ClipRect(), impeller::Paint::color, impeller::Canvas::DrawImageRect(), impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::Color::Magenta(), impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Scale().

## ◆ TEST_P() [147/419]

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

Definition at line 451 of file aiks_blur_unittests.cc.

451 {
452 Canvas canvas;
453
454 canvas.Scale(GetContentScale());
455 canvas.DrawRRect(Rect::MakeLTRB(0, 0, GetWindowSize().width, 100),
456 Size(10, 10), Paint{.color = Color::LimeGreen()});
457 canvas.DrawRRect(Rect::MakeLTRB(0, 110, GetWindowSize().width, 210),
458 Size(10, 10), Paint{.color = Color::Magenta()});
459 canvas.ClipRect(Rect::MakeLTRB(100, 0, 200, GetWindowSize().height));
460 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
461 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
462 FilterContents::BlurStyle::kNormal,
463 Entity::TileMode::kClamp));
464 canvas.Restore();
465
466 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
467 }

References impeller::Canvas::ClipRect(), impeller::Paint::color, impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::Color::LimeGreen(), impeller::Color::Magenta(), impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Scale().

## ◆ TEST_P() [148/419]

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

Definition at line 688 of file aiks_blur_unittests.cc.

688 {
689 for (int32_t i = 0; i < 5; ++i) {
690 Canvas canvas;
691 ISize clip_size = ISize(i, i);
692 canvas.ClipRect(
693 Rect::MakeXYWH(400, 400, clip_size.width, clip_size.height));
694 canvas.DrawCircle(
695 {400, 400}, 200,
696 {
697 .color = Color::Green(),
698 .image_filter = ImageFilter::MakeBlur(
699 Sigma(0.1), Sigma(0.1), FilterContents::BlurStyle::kNormal,
700 Entity::TileMode::kDecal),
701 });
702 canvas.Restore();
703
704 Picture picture = canvas.EndRecordingAsPicture();
705 std::shared_ptr<RenderTargetCache> cache =
706 std::make_shared<RenderTargetCache>(
707 GetContext()->GetResourceAllocator());
708 AiksContext aiks_context(GetContext(), nullptr, cache);
709 std::shared_ptr<Image> image = picture.ToImage(aiks_context, {1024, 768});
710 EXPECT_TRUE(image) << " clip rect " << i;
711 }
712 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::TSize< T >::height, impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Picture::ToImage(), and impeller::TSize< T >::width.

## ◆ TEST_P() [149/419]

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

Definition at line 1073 of file aiks_blur_unittests.cc.

1073 {
1074 size_t blur_required_mip_count =
1075 GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4;
1076 fml::testing::LogCapture log_capture;
1077 Canvas canvas;
1078 canvas.SaveLayer(
1079 {.image_filter = ImageFilter::MakeBlur(Sigma(30), Sigma(30),
1080 FilterContents::BlurStyle::kNormal,
1081 Entity::TileMode::kClamp)});
1082 canvas.DrawCircle({200, 200}, 50, {.color = Color::Chartreuse()});
1083
1084 Picture picture = canvas.EndRecordingAsPicture();
1085 std::shared_ptr<RenderTargetCache> cache =
1086 std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
1087 AiksContext aiks_context(GetContext(), nullptr, cache);
1088 picture.ToImage(aiks_context, {1024, 768});
1089
1090 size_t max_mip_count = 0;
1091 for (auto it = cache->GetRenderTargetDataBegin();
1092 it != cache->GetRenderTargetDataEnd(); ++it) {
1093 max_mip_count = std::max(it->config.mip_count, max_mip_count);
1094 }
1095 EXPECT_EQ(max_mip_count, blur_required_mip_count);
1096 // The log is FML_DLOG, so only check in debug builds.
1097 #ifndef NDEBUG
1098 if (GetParam() != PlaygroundBackend::kOpenGLES) {
1099 EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1100 std::string::npos);
1101 } else {
1102 EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1103 std::string::npos);
1104 }
1105 #endif
1106 }

References impeller::Color::Chartreuse(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::GaussianBlurFilterContents::kNoMipsError, impeller::FilterContents::kNormal, impeller::kOpenGLES, impeller::ImageFilter::MakeBlur(), impeller::Canvas::SaveLayer(), and impeller::Picture::ToImage().

## ◆ TEST_P() [150/419]

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

Definition at line 1034 of file aiks_blur_unittests.cc.

1034 {
1035 fml::testing::LogCapture log_capture;
1036 size_t blur_required_mip_count =
1037 GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4;
1038
1039 Canvas canvas;
1040 canvas.DrawPaint({.color = Color::Wheat()});
1041 canvas.SaveLayer({.blend_mode = BlendMode::kMultiply});
1042 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
1043 canvas.SaveLayer({}, std::nullopt,
1044 ImageFilter::MakeBlur(Sigma(30), Sigma(30),
1045 FilterContents::BlurStyle::kNormal,
1046 Entity::TileMode::kClamp));
1047 canvas.DrawCircle({200, 200}, 50, {.color = Color::Chartreuse()});
1048
1049 Picture picture = canvas.EndRecordingAsPicture();
1050 std::shared_ptr<RenderTargetCache> cache =
1051 std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
1052 AiksContext aiks_context(GetContext(), nullptr, cache);
1053 picture.ToImage(aiks_context, {100, 100});
1054
1055 size_t max_mip_count = 0;
1056 for (auto it = cache->GetRenderTargetDataBegin();
1057 it != cache->GetRenderTargetDataEnd(); ++it) {
1058 max_mip_count = std::max(it->config.mip_count, max_mip_count);
1059 }
1060 EXPECT_EQ(max_mip_count, blur_required_mip_count);
1061 // The log is FML_DLOG, so only check in debug builds.
1062 #ifndef NDEBUG
1063 if (GetParam() != PlaygroundBackend::kOpenGLES) {
1064 EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1065 std::string::npos);
1066 } else {
1067 EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1068 std::string::npos);
1069 }
1070 #endif
1071 }

References impeller::Color::Chartreuse(), impeller::Color::CornflowerBlue(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::kMultiply, impeller::GaussianBlurFilterContents::kNoMipsError, impeller::FilterContents::kNormal, impeller::kOpenGLES, impeller::ImageFilter::MakeBlur(), impeller::Canvas::SaveLayer(), impeller::Picture::ToImage(), and impeller::Color::Wheat().

## ◆ TEST_P() [151/419]

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

Definition at line 1108 of file aiks_blur_unittests.cc.

1108 {
1109 size_t blur_required_mip_count =
1110 GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4;
1111 fml::testing::LogCapture log_capture;
1112 Canvas canvas;
1113 canvas.DrawPath(PathBuilder{}
1114 .MoveTo({100, 100})
1115 .LineTo({200, 100})
1116 .LineTo({150, 200})
1117 .LineTo({50, 200})
1118 .Close()
1119 .TakePath(),
1120 {.color = Color::Chartreuse(),
1121 .image_filter = ImageFilter::MakeBlur(
1122 Sigma(30), Sigma(30), FilterContents::BlurStyle::kNormal,
1123 Entity::TileMode::kClamp)});
1124
1125 Picture picture = canvas.EndRecordingAsPicture();
1126 std::shared_ptr<RenderTargetCache> cache =
1127 std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
1128 AiksContext aiks_context(GetContext(), nullptr, cache);
1129 picture.ToImage(aiks_context, {1024, 768});
1130
1131 size_t max_mip_count = 0;
1132 for (auto it = cache->GetRenderTargetDataBegin();
1133 it != cache->GetRenderTargetDataEnd(); ++it) {
1134 max_mip_count = std::max(it->config.mip_count, max_mip_count);
1135 }
1136 EXPECT_EQ(max_mip_count, blur_required_mip_count);
1137 // The log is FML_DLOG, so only check in debug builds.
1138 #ifndef NDEBUG
1139 if (GetParam() != PlaygroundBackend::kOpenGLES) {
1140 EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1141 std::string::npos);
1142 } else {
1143 EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1144 std::string::npos);
1145 }
1146 #endif
1147 }

References impeller::Color::Chartreuse(), impeller::Close(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::GaussianBlurFilterContents::kNoMipsError, impeller::FilterContents::kNormal, impeller::kOpenGLES, impeller::LineTo(), impeller::ImageFilter::MakeBlur(), impeller::PathBuilder::MoveTo(), and impeller::Picture::ToImage().

## ◆ TEST_P() [152/419]

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

Definition at line 541 of file aiks_blur_unittests.cc.

541 {
542 Canvas canvas;
543
544 canvas.Scale(GetContentScale());
545 canvas.Scale({0.5, 0.5, 1.0});
546 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
547 canvas.DrawImage(std::make_shared<Image>(boston), Point(100, 100), Paint{});
548 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
549 ImageFilter::MakeBlur(Sigma(50.0), Sigma(0.0),
550 FilterContents::BlurStyle::kNormal,
551 Entity::TileMode::kClamp));
552 canvas.Restore();
553 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
554 }

References impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::ImageFilter::MakeBlur(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Scale().

## ◆ TEST_P() [153/419]

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

Definition at line 560 of file aiks_blur_unittests.cc.

560 {
561 Canvas canvas;
562 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
563 Rect bounds =
564 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
565 Vector2 image_center = Vector2(bounds.GetSize() / 2);
566 Paint paint = {.image_filter =
567 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
568 FilterContents::BlurStyle::kNormal,
569 Entity::TileMode::kDecal)};
570 Vector2 clip_size = {150, 75};
571 Vector2 center = Vector2(1024, 768) / 2;
572 canvas.Scale(GetContentScale());
573 canvas.ClipRect(
574 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size));
575 canvas.Translate({center.x, center.y, 0});
576 canvas.Scale({0.6, 0.6, 1});
577 canvas.Rotate(Degrees(25));
578
579 canvas.DrawImageRect(std::make_shared<Image>(boston), /*source=*/bounds,
580 /*dest=*/bounds.Shift(-image_center), paint);
581
582 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
583 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawImageRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< T >::Expand(), impeller::TRect< T >::GetSize(), impeller::Paint::image_filter, impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Rotate(), impeller::Canvas::Scale(), impeller::TRect< T >::Shift(), impeller::Canvas::Translate(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [154/419]

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

Definition at line 609 of file aiks_blur_unittests.cc.

609 {
610 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
611
612 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
613 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
614 const Entity::TileMode tile_modes[] = {
615 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
616 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
617
618 static float rotation = 0;
619 static float scale = 0.6;
620 static int selected_tile_mode = 3;
621
622 if (AiksTest::ImGuiBegin("Controls", nullptr,
623 ImGuiWindowFlags_AlwaysAutoResize)) {
624 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
625 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
626 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
627 sizeof(tile_mode_names) / sizeof(char*));
628 ImGui::End();
629 }
630
631 Canvas canvas;
632 Rect bounds =
633 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
634 Vector2 image_center = Vector2(bounds.GetSize() / 2);
635 Paint paint = {.image_filter =
636 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
637 FilterContents::BlurStyle::kNormal,
638 tile_modes[selected_tile_mode])};
639 static PlaygroundPoint point_a(Point(362, 309), 20, Color::Red());
640 static PlaygroundPoint point_b(Point(662, 459), 20, Color::Red());
641 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
642 Vector2 center = Vector2(1024, 768) / 2;
643 canvas.Scale(GetContentScale());
644 canvas.ClipRect(
645 Rect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
646 canvas.Translate({center.x, center.y, 0});
647 canvas.Scale({scale, scale, 1});
648 canvas.Rotate(Degrees(rotation));
649
650 canvas.DrawImageRect(std::make_shared<Image>(boston), /*source=*/bounds,
651 /*dest=*/bounds.Shift(-image_center), paint);
652 return canvas.EndRecordingAsPicture();
653 };
654
655 ASSERT_TRUE(OpenPlaygroundHere(callback));
656 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawImageRect(), impeller::DrawPlaygroundLine(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< T >::GetSize(), impeller::Paint::image_filter, impeller::AiksPlayground::ImGuiBegin(), impeller::Entity::kClamp, impeller::Entity::kDecal, impeller::Entity::kMirror, impeller::FilterContents::kNormal, impeller::Entity::kRepeat, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Rotate(), impeller::Canvas::Scale(), scale, impeller::TRect< T >::Shift(), impeller::Canvas::Translate(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [155/419]

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

Definition at line 585 of file aiks_blur_unittests.cc.

585 {
586 Canvas canvas;
587 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
588 Rect bounds =
589 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
590 Vector2 image_center = Vector2(bounds.GetSize() / 2);
591 Paint paint = {.image_filter =
592 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
593 FilterContents::BlurStyle::kNormal,
594 Entity::TileMode::kDecal)};
595 Vector2 clip_size = {150, 75};
596 Vector2 center = Vector2(1024, 768) / 2;
597 canvas.Scale(GetContentScale());
598 canvas.ClipRect(
599 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size));
600 canvas.Translate({center.x, center.y, 0});
601 canvas.Scale({0.6, 0.6, 1});
602
603 canvas.DrawImageRect(std::make_shared<Image>(boston), /*source=*/bounds,
604 /*dest=*/bounds.Shift(-image_center), paint);
605
606 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
607 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawImageRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< T >::Expand(), impeller::TRect< T >::GetSize(), impeller::Paint::image_filter, impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Scale(), impeller::TRect< T >::Shift(), impeller::Canvas::Translate(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [156/419]

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

Definition at line 995 of file aiks_blur_unittests.cc.

995 {
996 Canvas canvas;
997 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
998 canvas.SaveLayer({}, std::nullopt,
999 ImageFilter::MakeBlur(Sigma(3), Sigma(3),
1000 FilterContents::BlurStyle::kNormal,
1001 Entity::TileMode::kClamp));
1002 canvas.Restore();
1003
1004 Picture picture = canvas.EndRecordingAsPicture();
1005 EXPECT_EQ(4, picture.pass->GetRequiredMipCount());
1006 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::Picture::pass, impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [157/419]

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

Definition at line 661 of file aiks_blur_unittests.cc.

661 {
662 for (int32_t i = 1; i < 5; ++i) {
663 Canvas canvas;
664 Scalar fi = i;
665 canvas.DrawPath(
666 PathBuilder{}
667 .MoveTo({100, 100})
668 .LineTo({100.f + fi, 100.f + fi})
669 .TakePath(),
670 {.color = Color::Chartreuse(),
671 .image_filter = ImageFilter::MakeBlur(
672 Sigma(0.1), Sigma(0.1), FilterContents::BlurStyle::kNormal,
673 Entity::TileMode::kClamp)});
674
675 Picture picture = canvas.EndRecordingAsPicture();
676 std::shared_ptr<RenderTargetCache> cache =
677 std::make_shared<RenderTargetCache>(
678 GetContext()->GetResourceAllocator());
679 AiksContext aiks_context(GetContext(), nullptr, cache);
680 std::shared_ptr<Image> image = picture.ToImage(aiks_context, {1024, 768});
681 EXPECT_TRUE(image) << " length " << i;
682 }
683 }

References impeller::Color::Chartreuse(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::LineTo(), impeller::ImageFilter::MakeBlur(), impeller::PathBuilder::MoveTo(), and impeller::Picture::ToImage().

## ◆ TEST_P() [158/419]

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

Definition at line 857 of file aiks_blur_unittests.cc.

857 {
858 Canvas canvas;
859 canvas.Scale(GetContentScale());
860
861 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
862
863 Paint paint;
864 paint.color = Color::Green();
865 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
866 .style = FilterContents::BlurStyle::kInner,
867 .sigma = Sigma(30),
868 };
869 canvas.DrawPath(PathBuilder()
870 .MoveTo({200, 200})
871 .LineTo({300, 400})
872 .LineTo({100, 400})
873 .Close()
874 .TakePath(),
875 paint);
876
877 // Draw another thing to make sure the clip area is reset.
878 Paint red;
879 red.color = Color::Red();
880 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
881
882 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
883 }

References impeller::Close(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kInner, impeller::LineTo(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Paint::mask_blur_descriptor, impeller::MoveTo(), impeller::Color::Red(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [159/419]

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

Definition at line 758 of file aiks_blur_unittests.cc.

758 {
759 Canvas canvas;
760 canvas.Scale(GetContentScale());
761
762 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
763
764 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
765 Color{0.7568, 0.2627, 0.2118, 1.0}};
766 std::vector<Scalar> stops = {0.0, 1.0};
767
768 Paint paint;
769 paint.color_source = ColorSource::MakeLinearGradient(
770 {0, 0}, {200, 200}, std::move(colors), std::move(stops),
771 Entity::TileMode::kMirror, {});
772 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
773 .style = FilterContents::BlurStyle::kInner,
774 .sigma = Sigma(30),
775 };
776 canvas.DrawPath(PathBuilder()
777 .MoveTo({200, 200})
778 .LineTo({300, 400})
779 .LineTo({100, 400})
780 .Close()
781 .TakePath(),
782 paint);
783
784 // Draw another thing to make sure the clip area is reset.
785 Paint red;
786 red.color = Color::Red();
787 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
788 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
789 }

References impeller::Close(), impeller::Paint::color, impeller::Paint::color_source, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::FilterContents::kInner, impeller::Entity::kMirror, impeller::LineTo(), impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Paint::mask_blur_descriptor, impeller::MoveTo(), impeller::Color::Red(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [160/419]

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

Definition at line 885 of file aiks_blur_unittests.cc.

885 {
886 Canvas canvas;
887 canvas.Scale(GetContentScale());
888
889 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
890
891 Paint paint;
892 paint.color = Color::Green();
893 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
894 .style = FilterContents::BlurStyle::kOuter,
895 .sigma = Sigma(30),
896 };
897 canvas.DrawPath(PathBuilder()
898 .MoveTo({200, 200})
899 .LineTo({300, 400})
900 .LineTo({100, 400})
901 .Close()
902 .TakePath(),
903 paint);
904
905 // Draw another thing to make sure the clip area is reset.
906 Paint red;
907 red.color = Color::Red();
908 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
909
910 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
911 }

References impeller::Close(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kOuter, impeller::LineTo(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Paint::mask_blur_descriptor, impeller::MoveTo(), impeller::Color::Red(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [161/419]

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

Definition at line 824 of file aiks_blur_unittests.cc.

824 {
825 Canvas canvas;
826 canvas.Scale(GetContentScale());
827
828 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
829
830 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
831 Color{0.7568, 0.2627, 0.2118, 1.0}};
832 std::vector<Scalar> stops = {0.0, 1.0};
833
834 Paint paint;
835 paint.color_source = ColorSource::MakeLinearGradient(
836 {0, 0}, {200, 200}, std::move(colors), std::move(stops),
837 Entity::TileMode::kMirror, {});
838 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
839 .style = FilterContents::BlurStyle::kOuter,
840 .sigma = Sigma(30),
841 };
842 canvas.DrawPath(PathBuilder()
843 .MoveTo({200, 200})
844 .LineTo({300, 400})
845 .LineTo({100, 400})
846 .Close()
847 .TakePath(),
848 paint);
849
850 // Draw another thing to make sure the clip area is reset.
851 Paint red;
852 red.color = Color::Red();
853 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
854 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
855 }

References impeller::Close(), impeller::Paint::color, impeller::Paint::color_source, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kMirror, impeller::FilterContents::kOuter, impeller::LineTo(), impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Paint::mask_blur_descriptor, impeller::MoveTo(), impeller::Color::Red(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [162/419]

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

Definition at line 913 of file aiks_blur_unittests.cc.

913 {
914 Canvas canvas;
915 canvas.Scale(GetContentScale());
916
917 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
918
919 Paint paint;
920 paint.color = Color::Green();
921 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
922 .style = FilterContents::BlurStyle::kSolid,
923 .sigma = Sigma(30),
924 };
925 canvas.DrawPath(PathBuilder()
926 .MoveTo({200, 200})
927 .LineTo({300, 400})
928 .LineTo({100, 400})
929 .Close()
930 .TakePath(),
931 paint);
932
933 // Draw another thing to make sure the clip area is reset.
934 Paint red;
935 red.color = Color::Red();
936 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
937
938 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
939 }

References impeller::Close(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kSolid, impeller::LineTo(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Paint::mask_blur_descriptor, impeller::MoveTo(), impeller::Color::Red(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [163/419]

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

Definition at line 791 of file aiks_blur_unittests.cc.

791 {
792 Canvas canvas;
793 canvas.Scale(GetContentScale());
794
795 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
796
797 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
798 Color{0.7568, 0.2627, 0.2118, 1.0}};
799 std::vector<Scalar> stops = {0.0, 1.0};
800
801 Paint paint;
802 paint.color_source = ColorSource::MakeLinearGradient(
803 {0, 0}, {200, 200}, std::move(colors), std::move(stops),
804 Entity::TileMode::kMirror, {});
805 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
806 .style = FilterContents::BlurStyle::kSolid,
807 .sigma = Sigma(30),
808 };
809 canvas.DrawPath(PathBuilder()
810 .MoveTo({200, 200})
811 .LineTo({300, 400})
812 .LineTo({100, 400})
813 .Close()
814 .TakePath(),
815 paint);
816
817 // Draw another thing to make sure the clip area is reset.
818 Paint red;
819 red.color = Color::Red();
820 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
821 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
822 }

References impeller::Close(), impeller::Paint::color, impeller::Paint::color_source, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kMirror, impeller::FilterContents::kSolid, impeller::LineTo(), impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Paint::mask_blur_descriptor, impeller::MoveTo(), impeller::Color::Red(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [164/419]

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

Definition at line 493 of file aiks_blur_unittests.cc.

493 {
494 if (GetParam() != PlaygroundBackend::kMetal) {
495 GTEST_SKIP_(
496 "This backend doesn't yet support setting device capabilities.");
497 }
498 if (!WillRenderSomething()) {
499 // Sometimes these tests are run without playgrounds enabled which is
500 // pointless for this test since we are asserting that
501 // `SupportsDecalSamplerAddressMode` is called.
502 GTEST_SKIP_("This test requires playgrounds.");
503 }
504
505 std::shared_ptr<const Capabilities> old_capabilities =
506 GetContext()->GetCapabilities();
507 auto mock_capabilities = std::make_shared<MockCapabilities>();
508 EXPECT_CALL(*mock_capabilities, SupportsDecalSamplerAddressMode())
509 .Times(::testing::AtLeast(1))
510 .WillRepeatedly(::testing::Return(false));
511 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultColorFormat);
512 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultStencilFormat);
513 FLT_FORWARD(mock_capabilities, old_capabilities,
514 GetDefaultDepthStencilFormat);
515 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsOffscreenMSAA);
516 FLT_FORWARD(mock_capabilities, old_capabilities,
517 SupportsImplicitResolvingMSAA);
518 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsReadFromResolve);
519 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsFramebufferFetch);
520 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsSSBO);
521 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsCompute);
522 FLT_FORWARD(mock_capabilities, old_capabilities,
523 SupportsTextureToTextureBlits);
524 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultGlyphAtlasFormat);
525 ASSERT_TRUE(SetCapabilities(mock_capabilities).ok());
526
527 auto texture = std::make_shared<Image>(CreateTextureForFixture("boston.jpg"));
528 Canvas canvas;
529 canvas.Scale(GetContentScale() * 0.5);
530 canvas.DrawPaint({.color = Color::Black()});
531 canvas.DrawImage(
532 texture, Point(200, 200),
533 {
534 .image_filter = ImageFilter::MakeBlur(
535 Sigma(20.0), Sigma(20.0), FilterContents::BlurStyle::kNormal,
536 Entity::TileMode::kDecal),
537 });
538 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
539 }

References impeller::Color::Black(), impeller::Canvas::DrawImage(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), FLT_FORWARD, impeller::Entity::kDecal, impeller::kMetal, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), and impeller::Canvas::Scale().

## ◆ TEST_P() [165/419]

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

Definition at line 654 of file aiks_gradient_unittests.cc.

654 {
655 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
656 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
657 static float scale = 3;
658 static bool add_circle_clip = true;
659 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
660 const Entity::TileMode tile_modes[] = {
661 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
662 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
663 static int selected_tile_mode = 0;
664 static float alpha = 1;
665
666 if (AiksTest::ImGuiBegin("Controls", nullptr,
667 ImGuiWindowFlags_AlwaysAutoResize)) {
668 ImGui::SliderFloat("Scale", &scale, 0, 6);
669 ImGui::Checkbox("Circle clip", &add_circle_clip);
670 ImGui::SliderFloat("Alpha", &alpha, 0, 1);
671 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
672 sizeof(tile_mode_names) / sizeof(char*));
673 ImGui::End();
674 }
675
676 Canvas canvas;
677 canvas.Scale(GetContentScale());
678 Paint paint;
679 paint.color = Color::White();
680 canvas.DrawPaint(paint);
681
682 paint.style = Paint::Style::kStroke;
683 paint.color = Color(1.0, 1.0, 1.0, alpha);
684 paint.stroke_width = 10;
685 auto tile_mode = tile_modes[selected_tile_mode];
686
687 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
688 Color{0.1294, 0.5882, 0.9529, 1.0}};
689 std::vector<Scalar> stops = {0.0, 1.0};
690
691 paint.color_source = ColorSource::MakeLinearGradient(
692 {0, 0}, {50, 50}, std::move(colors), std::move(stops), tile_mode, {});
693
694 Path path = PathBuilder{}
695 .MoveTo({20, 20})
696 .QuadraticCurveTo({60, 20}, {60, 60})
697 .Close()
698 .MoveTo({60, 20})
699 .QuadraticCurveTo({60, 60}, {20, 60})
700 .TakePath();
701
702 canvas.Scale(Vector2(scale, scale));
703
704 if (add_circle_clip) {
705 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
706 Color::Red());
707 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
708 Color::Red());
709 auto [handle_a, handle_b] =
710 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
711
712 auto screen_to_canvas = canvas.GetCurrentTransform().Invert();
713 Point point_a = screen_to_canvas * handle_a * GetContentScale();
714 Point point_b = screen_to_canvas * handle_b * GetContentScale();
715
716 Point middle = (point_a + point_b) / 2;
717 auto radius = point_a.GetDistance(middle);
718 canvas.ClipPath(PathBuilder{}.AddCircle(middle, radius).TakePath());
719 }
720
721 for (auto join : {Join::kBevel, Join::kRound, Join::kMiter}) {
722 paint.stroke_join = join;
723 for (auto cap : {Cap::kButt, Cap::kSquare, Cap::kRound}) {
724 paint.stroke_cap = cap;
725 canvas.DrawPath(path, paint);
726 canvas.Translate({80, 0});
727 }
728 canvas.Translate({-240, 60});
729 }
730
731 return canvas.EndRecordingAsPicture();
732 };
733
734 ASSERT_TRUE(OpenPlaygroundHere(callback));
735 }

References impeller::PathBuilder::AddCircle(), impeller::Canvas::ClipPath(), impeller::Close(), impeller::Paint::color, impeller::Paint::color_source, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::DrawPlaygroundLine(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::GetCurrentTransform(), impeller::TPoint< T >::GetDistance(), impeller::AiksPlayground::ImGuiBegin(), impeller::Matrix::Invert(), impeller::kBevel, impeller::kButt, impeller::Entity::kClamp, impeller::Entity::kDecal, impeller::Entity::kMirror, impeller::kMiter, impeller::Entity::kRepeat, impeller::kRound, impeller::kSquare, impeller::Paint::kStroke, impeller::ColorSource::MakeLinearGradient(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Canvas::Scale(), scale, impeller::Paint::stroke_cap, impeller::Paint::stroke_join, impeller::Paint::stroke_width, impeller::Paint::style, impeller::PathBuilder::TakePath(), impeller::Canvas::Translate(), and impeller::Color::White().

## ◆ TEST_P() [166/419]

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

Definition at line 967 of file aiks_blur_unittests.cc.

967 {
968 // This makes sure if mip maps are recycled across invocations of blurs the
969 // contents get updated each frame correctly. If they aren't updated the color
970 // inside the blur and outside the blur will be different.
971 //
972 // If there is some change to render target caching this could display a false
973 // positive in the future. Also, if the LOD that is rendered is 1 it could
974 // present a false positive.
975 int32_t count = 0;
976 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
977 Canvas canvas;
978 if (count++ == 0) {
979 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
980 } else {
981 canvas.DrawCircle({100, 100}, 50, {.color = Color::Chartreuse()});
982 }
983 canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), {20, 20});
984 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
985 ImageFilter::MakeBlur(Sigma(30.0), Sigma(30.0),
986 FilterContents::BlurStyle::kNormal,
987 Entity::TileMode::kClamp));
988 canvas.Restore();
989 return canvas.EndRecordingAsPicture();
990 };
991
992 ASSERT_TRUE(OpenPlaygroundHere(callback));
993 }

References impeller::Color::Chartreuse(), impeller::Canvas::ClipRRect(), impeller::Color::CornflowerBlue(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [167/419]

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

Definition at line 3287 of file aiks_unittests.cc.

3287 {
3288 // Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885
3289
3290 Canvas canvas;
3291 auto texture = CreateTextureForFixture("monkey.png");
3292
3293 canvas.DrawPaint({.color = Color::White()});
3294
3295 // Translation
3296 {
3297 Paint paint;
3298 paint.color_source = ColorSource::MakeImage(
3299 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
3300 Matrix::MakeTranslation({50, 50}));
3301 canvas.DrawRect(Rect::MakeLTRB(0, 0, 100, 100), paint);
3302 }
3303
3304 // Rotation/skew
3305 {
3306 canvas.Save();
3307 canvas.Rotate(Degrees(45));
3308 Paint paint;
3309 paint.color_source = ColorSource::MakeImage(
3310 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
3311 Matrix(1, -1, 0, 0, //
3312 1, 1, 0, 0, //
3313 0, 0, 1, 0, //
3314 0, 0, 0, 1) //
3315 );
3316 canvas.DrawRect(Rect::MakeLTRB(100, 0, 200, 100), paint);
3317 canvas.Restore();
3318 }
3319
3320 // Scale
3321 {
3322 canvas.Translate(Vector2(100, 0));
3323 canvas.Scale(Vector2(100, 100));
3324 Paint paint;
3325 paint.color_source = ColorSource::MakeImage(
3326 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
3327 Matrix::MakeScale(Vector2(0.005, 0.005)));
3328 canvas.DrawRect(Rect::MakeLTRB(0, 0, 1, 1), paint);
3329 }
3330
3331 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3332 }

References impeller::Paint::color_source, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kRepeat, impeller::ColorSource::MakeImage(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Restore(), impeller::Canvas::Rotate(), impeller::Canvas::Save(), impeller::Canvas::Scale(), impeller::Canvas::Translate(), and impeller::Color::White().

## ◆ TEST_P() [168/419]

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

Definition at line 2419 of file aiks_unittests.cc.

2419 {
2420 Canvas canvas;
2421 canvas.Scale(GetContentScale());
2422
2423 auto test = [&canvas](const std::shared_ptr<ImageFilter>& filter) {
2424 auto DrawLine = [&canvas](const Point& p0, const Point& p1,
2425 const Paint& p) {
2426 auto path = PathBuilder{}
2427 .AddLine(p0, p1)
2428 .SetConvexity(Convexity::kConvex)
2429 .TakePath();
2430 Paint paint = p;
2431 paint.style = Paint::Style::kStroke;
2432 canvas.DrawPath(path, paint);
2433 };
2434 // Registration marks for the edge of the SaveLayer
2435 DrawLine(Point(75, 100), Point(225, 100), {.color = Color::White()});
2436 DrawLine(Point(75, 200), Point(225, 200), {.color = Color::White()});
2437 DrawLine(Point(100, 75), Point(100, 225), {.color = Color::White()});
2438 DrawLine(Point(200, 75), Point(200, 225), {.color = Color::White()});
2439
2440 canvas.SaveLayer({.image_filter = filter},
2441 Rect::MakeLTRB(100, 100, 200, 200));
2442 {
2443 // DrawPaint to verify correct behavior when the contents are unbounded.
2444 canvas.DrawPaint({.color = Color::Yellow()});
2445
2446 // Contrasting rectangle to see interior blurring
2447 canvas.DrawRect(Rect::MakeLTRB(125, 125, 175, 175),
2448 {.color = Color::Blue()});
2449 }
2450 canvas.Restore();
2451 };
2452
2453 test(ImageFilter::MakeBlur(Sigma{10.0}, Sigma{10.0},
2454 FilterContents::BlurStyle::kNormal,
2455 Entity::TileMode::kDecal));
2456
2457 canvas.Translate({200.0, 0.0});
2458
2459 test(ImageFilter::MakeDilate(Radius{10.0}, Radius{10.0}));
2460
2461 canvas.Translate({200.0, 0.0});
2462
2463 test(ImageFilter::MakeErode(Radius{10.0}, Radius{10.0}));
2464
2465 canvas.Translate({-400.0, 200.0});
2466
2467 auto rotate_filter =
2468 ImageFilter::MakeMatrix(Matrix::MakeTranslation({150, 150}) *
2469 Matrix::MakeRotationZ(Degrees{10.0}) *
2470 Matrix::MakeTranslation({-150, -150}),
2471 SamplerDescriptor{});
2472 test(rotate_filter);
2473
2474 canvas.Translate({200.0, 0.0});
2475
2476 auto rgb_swap_filter = ImageFilter::MakeFromColorFilter(
2477 *ColorFilter::MakeMatrix({.array = {
2478 0, 1, 0, 0, 0, //
2479 0, 0, 1, 0, 0, //
2480 1, 0, 0, 0, 0, //
2481 0, 0, 0, 1, 0 //
2482 }}));
2483 test(rgb_swap_filter);
2484
2485 canvas.Translate({200.0, 0.0});
2486
2487 test(ImageFilter::MakeCompose(*rotate_filter, *rgb_swap_filter));
2488
2489 canvas.Translate({-400.0, 200.0});
2490
2491 test(ImageFilter::MakeLocalMatrix(Matrix::MakeTranslation({25.0, 25.0}),
2492 *rotate_filter));
2493
2494 canvas.Translate({200.0, 0.0});
2495
2496 test(ImageFilter::MakeLocalMatrix(Matrix::MakeTranslation({25.0, 25.0}),
2497 *rgb_swap_filter));
2498
2499 canvas.Translate({200.0, 0.0});
2500
2501 test(ImageFilter::MakeLocalMatrix(
2502 Matrix::MakeTranslation({25.0, 25.0}),
2503 *ImageFilter::MakeCompose(*rotate_filter, *rgb_swap_filter)));
2504
2505 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2506 }

References impeller::PathBuilder::AddLine(), impeller::Color::Blue(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kConvex, impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::Paint::kStroke, impeller::ImageFilter::MakeBlur(), impeller::ImageFilter::MakeCompose(), impeller::ImageFilter::MakeDilate(), impeller::ImageFilter::MakeErode(), impeller::ImageFilter::MakeFromColorFilter(), impeller::ImageFilter::MakeLocalMatrix(), impeller::TRect< Scalar >::MakeLTRB(), impeller::ColorFilter::MakeMatrix(), impeller::ImageFilter::MakeMatrix(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), impeller::PathBuilder::SetConvexity(), impeller::Paint::style, impeller::PathBuilder::TakePath(), impeller::Canvas::Translate(), impeller::Color::White(), and impeller::Color::Yellow().

## ◆ TEST_P() [169/419]

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

Definition at line 2508 of file aiks_unittests.cc.

2508 {
2509 Canvas canvas;
2510 canvas.Scale(GetContentScale());
2511
2512 auto blur_filter = ImageFilter::MakeBlur(Sigma{10.0}, Sigma{10.0},
2513 FilterContents::BlurStyle::kNormal,
2514 Entity::TileMode::kDecal);
2515
2516 canvas.SaveLayer({.image_filter = blur_filter}, std::nullopt);
2517 {
2518 // DrawPaint to verify correct behavior when the contents are unbounded.
2519 canvas.DrawPaint({.color = Color::Yellow()});
2520
2521 // Contrasting rectangle to see interior blurring
2522 canvas.DrawRect(Rect::MakeLTRB(125, 125, 175, 175),
2523 {.color = Color::Blue()});
2524 }
2525 canvas.Restore();
2526
2527 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2528 }

References impeller::Color::Blue(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), and impeller::Color::Yellow().

## ◆ TEST_P() [170/419]

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

Definition at line 2205 of file aiks_unittests.cc.

2205 {
2206 Canvas canvas;
2207
2208 canvas.SaveLayer({
2209 .color_filter = ColorFilter::MakeLinearToSrgb(),
2210 });
2211
2212 canvas.Translate({500, 300, 0});
2213 canvas.Rotate(Radians(2 * kPi / 3));
2214 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
2215
2216 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2217 }

References impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kPi, impeller::ColorFilter::MakeLinearToSrgb(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Rotate(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [171/419]

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

Definition at line 1149 of file aiks_blur_unittests.cc.

1149 {
1150 Scalar sigma = 70;
1151 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1152 if (AiksTest::ImGuiBegin("Controls", nullptr,
1153 ImGuiWindowFlags_AlwaysAutoResize)) {
1154 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
1155 ImGui::End();
1156 }
1157 Canvas canvas;
1158 canvas.Scale(GetContentScale());
1159 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
1160
1161 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1162 ColorSource image_source = ColorSource::MakeImage(
1163 boston, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {}, {});
1164
1165 canvas.Transform(Matrix::MakeTranslation({100, 100, 0}) *
1166 Matrix::MakeScale({0.5, 0.5, 1.0}));
1167 Paint paint = {
1168 .color_source = image_source,
1169 .mask_blur_descriptor =
1170 Paint::MaskBlurDescriptor{
1171 .style = FilterContents::BlurStyle::kNormal,
1172 .sigma = Sigma(sigma),
1173 },
1174 };
1175 canvas.DrawRect(
1176 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
1177 paint);
1178
1179 return canvas.EndRecordingAsPicture();
1180 };
1181 ASSERT_TRUE(OpenPlaygroundHere(callback));
1182 }

References impeller::Paint::color_source, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::AiksPlayground::ImGuiBegin(), impeller::FilterContents::kNormal, impeller::Entity::kRepeat, impeller::ColorSource::MakeImage(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Scale(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Canvas::Transform().

## ◆ TEST_P() [172/419]

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

Definition at line 941 of file aiks_blur_unittests.cc.

941 {
942 Scalar sigma = 30;
943 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
944 if (AiksTest::ImGuiBegin("Controls", nullptr,
945 ImGuiWindowFlags_AlwaysAutoResize)) {
946 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
947 ImGui::End();
948 }
949 Canvas canvas;
950 canvas.Scale(GetContentScale());
951 Paint paint;
952 paint.color = Color::Green();
953 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
954 .style = FilterContents::BlurStyle::kNormal,
955 .sigma = Sigma(sigma),
956 };
957 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
958 canvas.DrawImage(std::make_shared<Image>(boston), {200, 200}, paint);
959 Paint red;
960 red.color = Color::Red();
961 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
962 return canvas.EndRecordingAsPicture();
963 };
964 ASSERT_TRUE(OpenPlaygroundHere(callback));
965 }

References impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::AiksPlayground::ImGuiBegin(), impeller::FilterContents::kNormal, impeller::TRect< Scalar >::MakeXYWH(), impeller::Paint::mask_blur_descriptor, impeller::Color::Red(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [173/419]

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

Definition at line 267 of file aiks_blur_unittests.cc.

267 {
268 Canvas canvas;
269
270 Paint paint = {
271 .color = Color::Blue(),
272 .mask_blur_descriptor =
273 Paint::MaskBlurDescriptor{
274 .style = FilterContents::BlurStyle::kNormal,
275 .sigma = Sigma(0),
276 },
277 };
278
279 canvas.DrawCircle({300, 300}, 200, paint);
280 canvas.DrawRect(Rect::MakeLTRB(100, 300, 500, 600), paint);
281
282 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
283 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::FilterContents::kNormal, impeller::TRect< Scalar >::MakeLTRB(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [174/419]

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

Definition at line 2963 of file aiks_unittests.cc.

2963 {
2964 Canvas canvas;
2965 canvas.DrawPaint({.color = Color::Black()});
2966 canvas.SaveLayer({}, std::nullopt);
2967 {
2968 canvas.DrawCircle(Point(200, 200), 100,
2969 {.color = Color::Green().WithAlpha(0.5),
2970 .blend_mode = BlendMode::kPlus});
2971 // Should render a second circle, centered on the bottom-right-most edge of
2972 // the circle.
2973 canvas.SaveLayer(
2974 {}, std::nullopt,
2975 ImageFilter::MakeMatrix(
2976 Matrix::MakeTranslation(Vector2(1, 1) * (100 + 100 * k1OverSqrt2)) *
2977 Matrix::MakeScale(Vector2(1, 1) * 0.5) *
2978 Matrix::MakeTranslation(Vector2(-100, -100)),
2979 SamplerDescriptor{}));
2980 canvas.Restore();
2981 }
2982 canvas.Restore();
2983
2984 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2985 }

References impeller::Color::Black(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::k1OverSqrt2, impeller::kPlus, impeller::ImageFilter::MakeMatrix(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [175/419]

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

Definition at line 3206 of file aiks_unittests.cc.

3207 {
3208 Canvas canvas;
3209 canvas.Scale(GetContentScale());
3210 canvas.Translate({100, 100});
3211 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
3212 // +300 translation applied by a SaveLayer image filter.
3213 canvas.SaveLayer({
3214 .image_filter = std::make_shared<MatrixImageFilter>(
3215 Matrix::MakeTranslation({300, 0}) * Matrix::MakeScale({2, 2, 2}),
3216 SamplerDescriptor{}),
3217 });
3218 canvas.DrawCircle({-150, 0}, 50, {.color = Color::Green()});
3219 canvas.Restore();
3220
3221 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3222 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [176/419]

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

Definition at line 3189 of file aiks_unittests.cc.

3189 {
3190 Canvas canvas;
3191 canvas.Scale(GetContentScale());
3192 canvas.Translate({100, 100});
3193 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
3194 // +300 translation applied by a SaveLayer image filter.
3195 canvas.SaveLayer({
3196 .image_filter = std::make_shared<MatrixImageFilter>(
3197 Matrix::MakeTranslation({300, 0}), SamplerDescriptor{}),
3198 });
3199 canvas.DrawCircle({-300, 0}, 100, {.color = Color::Green()});
3200 canvas.Restore();
3201
3202 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3203 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [177/419]

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

Definition at line 3172 of file aiks_unittests.cc.

3172 {
3173 Canvas canvas;
3174 canvas.Scale(GetContentScale());
3175 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
3176 canvas.Translate({600, -200});
3177 canvas.SaveLayer({
3178 .image_filter = std::make_shared<MatrixImageFilter>(
3179 Matrix::MakeScale({2, 2, 2}), SamplerDescriptor{}),
3180 });
3181 canvas.DrawImage(image, {0, 0},
3182 Paint{.color = Color::White().WithAlpha(0.5)});
3183 canvas.Restore();
3184
3185 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3186 }

References impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Matrix::MakeScale(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), impeller::Canvas::Translate(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [178/419]

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

Definition at line 2936 of file aiks_unittests.cc.

2936 {
2937 Canvas canvas;
2938 canvas.DrawPaint({.color = Color::Black()});
2939 canvas.SaveLayer({}, std::nullopt);
2940 {
2941 canvas.DrawCircle(Point(200, 200), 100,
2942 {.color = Color::Green().WithAlpha(0.5),
2943 .blend_mode = BlendMode::kPlus});
2944 // Should render a second circle, centered on the bottom-right-most edge of
2945 // the circle.
2946 canvas.SaveLayer({.image_filter = ImageFilter::MakeMatrix(
2947 Matrix::MakeTranslation(Vector2(1, 1) *
2948 (200 + 100 * k1OverSqrt2)) *
2949 Matrix::MakeScale(Vector2(1, 1) * 0.5) *
2950 Matrix::MakeTranslation(Vector2(-200, -200)),
2951 SamplerDescriptor{})},
2952 std::nullopt);
2953 canvas.DrawCircle(Point(200, 200), 100,
2954 {.color = Color::Green().WithAlpha(0.5),
2955 .blend_mode = BlendMode::kPlus});
2956 canvas.Restore();
2957 }
2958 canvas.Restore();
2959
2960 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2961 }

References impeller::Color::Black(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::k1OverSqrt2, impeller::kPlus, impeller::ImageFilter::MakeMatrix(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [179/419]

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

Definition at line 1925 of file aiks_unittests.cc.

1925 {
1926 auto entity_pass = std::make_shared<EntityPass>();
1927 auto rect = Rect::MakeLTRB(0, 0, 100, 100);
1928 Paint paint;
1929 paint.color = Color::White().WithAlpha(0.5);
1930 paint.color_filter =
1931 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Blue());
1932
1933 // Paint has color filter, can't elide.
1934 auto delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
1935 ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
1936
1937 paint.color_filter = nullptr;
1938 paint.image_filter = ImageFilter::MakeBlur(Sigma(1.0), Sigma(1.0),
1939 FilterContents::BlurStyle::kNormal,
1940 Entity::TileMode::kClamp);
1941
1942 // Paint has image filter, can't elide.
1943 delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
1944 ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
1945
1946 paint.image_filter = nullptr;
1947 paint.color = Color::Red();
1948
1949 // Paint has no alpha, can't elide;
1950 delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
1951 ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
1952
1953 // Positive test.
1954 Entity entity;
1955 entity.SetContents(SolidColorContents::Make(
1956 PathBuilder{}.AddRect(rect).TakePath(), Color::Red()));
1957 entity_pass->AddEntity(std::move(entity));
1958 paint.color = Color::Red().WithAlpha(0.5);
1959
1960 delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
1961 ASSERT_TRUE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
1962 }

References impeller::PathBuilder::AddRect(), impeller::Color::Blue(), impeller::Paint::color, impeller::Paint::color_filter, impeller::Paint::image_filter, impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSourceOver, impeller::SolidColorContents::Make(), impeller::ColorFilter::MakeBlend(), impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Color::Red(), impeller::Entity::SetContents(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [180/419]

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

Definition at line 2670 of file aiks_unittests.cc.

2670 {
2671 Canvas canvas;
2672 canvas.Scale(Vector2(1.618, 1.618));
2673 canvas.DrawCircle(Point(), 10,
2674 {
2675 .color = Color::CornflowerBlue(),
2676 .blend_mode = BlendMode::kSourceOver,
2677 });
2678 Picture picture = canvas.EndRecordingAsPicture();
2679
2680 // Extract the SolidColorSource.
2681 // Entity entity;
2682 std::vector<Entity> entity;
2683 std::shared_ptr<SolidColorContents> contents;
2684 picture.pass->IterateAllEntities([e = &entity, &contents](Entity& entity) {
2685 if (ScalarNearlyEqual(entity.GetTransform().GetScale().x, 1.618f)) {
2686 contents =
2687 std::static_pointer_cast<SolidColorContents>(entity.GetContents());
2688 e->emplace_back(entity.Clone());
2689 return false;
2690 }
2691 return true;
2692 });
2693
2694 ASSERT_TRUE(entity.size() >= 1);
2695 ASSERT_TRUE(contents->IsOpaque());
2696 ASSERT_EQ(entity[0].GetBlendMode(), BlendMode::kSource);
2697 }

References impeller::Entity::Clone(), impeller::Color::CornflowerBlue(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::GetContents(), impeller::Matrix::GetScale(), impeller::Entity::GetTransform(), impeller::kSource, impeller::kSourceOver, impeller::Picture::pass, impeller::ScalarNearlyEqual(), impeller::Canvas::Scale(), and impeller::Vector3::x.

## ◆ TEST_P() [181/419]

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

Definition at line 1086 of file aiks_unittests.cc.

1086 {
1087 Paint paint;
1088 Canvas canvas;
1089 // Default is kSourceOver.
1090 paint.color = Color(1, 0, 0, 0.5);
1091 canvas.DrawCircle(Point(150, 200), 100, paint);
1092 paint.color = Color(0, 1, 0, 0.5);
1093 canvas.DrawCircle(Point(250, 200), 100, paint);
1094
1095 paint.blend_mode = BlendMode::kPlus;
1096 paint.color = Color::Red();
1097 canvas.DrawCircle(Point(450, 250), 100, paint);
1098 paint.color = Color::Green();
1099 canvas.DrawCircle(Point(550, 250), 100, paint);
1100 paint.color = Color::Blue();
1101 canvas.DrawCircle(Point(500, 150), 100, paint);
1102 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1103 }

References impeller::Paint::blend_mode, impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::kPlus, and impeller::Color::Red().

## ◆ TEST_P() [182/419]

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

Definition at line 1898 of file aiks_unittests.cc.

1898 {
1899 // validate that a paint with a color filter "HasFilters", no other filters
1900 // impact this setting.
1901 Paint paint;
1902
1903 ASSERT_FALSE(paint.HasColorFilter());
1904
1905 paint.color_filter =
1906 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Blue());
1907
1908 ASSERT_TRUE(paint.HasColorFilter());
1909
1910 paint.image_filter = ImageFilter::MakeBlur(Sigma(1.0), Sigma(1.0),
1911 FilterContents::BlurStyle::kNormal,
1912 Entity::TileMode::kClamp);
1913
1914 ASSERT_TRUE(paint.HasColorFilter());
1915
1916 paint.mask_blur_descriptor = {};
1917
1918 ASSERT_TRUE(paint.HasColorFilter());
1919
1920 paint.color_filter = nullptr;
1921
1922 ASSERT_FALSE(paint.HasColorFilter());
1923 }

References impeller::Color::Blue(), impeller::Paint::color_filter, impeller::Paint::HasColorFilter(), impeller::Paint::image_filter, impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSourceOver, impeller::ColorFilter::MakeBlend(), impeller::ImageFilter::MakeBlur(), and impeller::Paint::mask_blur_descriptor.

## ◆ TEST_P() [183/419]

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

Definition at line 1988 of file aiks_unittests.cc.

1989 {
1990 Canvas canvas;
1991 canvas.SaveLayer({}, std::nullopt, ImageFilter::MakeMatrix(Matrix(), {}));
1992 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
1993 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
1994 .blend_mode = BlendMode::kSourceOver});
1995 canvas.Restore();
1996
1997 Picture picture = canvas.EndRecordingAsPicture();
1998
1999 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2000 std::shared_ptr<Context> real_context = GetContext();
2001 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2002 AiksContext renderer(mock_context, nullptr);
2003 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
2004
2005 ASSERT_EQ(spy->render_passes_.size(),
2006 GetBackend() == PlaygroundBackend::kOpenGLES ? 4llu : 3llu);
2007 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2008 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
2009 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kOpenGLES, impeller::kSource, impeller::kSourceOver, impeller::ImageFilter::MakeMatrix(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Picture::ToImage(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [184/419]

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

Definition at line 3027 of file aiks_unittests.cc.

3027 {
3028 Canvas canvas;
3029
3030 // Should render a green square in the middle of a blue circle.
3031 canvas.SaveLayer({});
3032 {
3033 canvas.Translate(Point(100, 100));
3034 canvas.DrawCircle(Point(200, 200), 200, {.color = Color::Blue()});
3035 canvas.ClipRect(Rect::MakeXYWH(100, 100, 200, 200));
3036 canvas.DrawCircle(Point(200, 200), 200,
3037 {
3038 .color = Color::Green(),
3039 .blend_mode = BlendMode::kSourceOver,
3040 .image_filter = ImageFilter::MakeFromColorFilter(
3041 *ColorFilter::MakeBlend(BlendMode::kDestination,
3042 Color::White())),
3043 });
3044 canvas.Restore();
3045 }
3046
3047 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3048 }

References impeller::Color::Blue(), impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::kDestination, impeller::kSourceOver, impeller::ColorFilter::MakeBlend(), impeller::ImageFilter::MakeFromColorFilter(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Translate(), and impeller::Color::White().

## ◆ TEST_P() [185/419]

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

Definition at line 3083 of file aiks_unittests.cc.

3083 {
3084 auto context = MakeContext();
3085 std::weak_ptr<Texture> weak_texture;
3086
3087 {
3088 auto texture = CreateTextureForFixture("table_mountain_nx.png");
3089
3090 Canvas canvas;
3091 canvas.Scale(GetContentScale());
3092 canvas.Translate({100.0f, 100.0f, 0});
3093
3094 Paint paint;
3095 paint.color_source = ColorSource::MakeImage(
3096 texture, Entity::TileMode::kClamp, Entity::TileMode::kClamp, {}, {});
3097 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
3098
3099 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3100 }
3101
3102 // See https://github.com/flutter/flutter/issues/134751.
3103 //
3104 // If the fence waiter was working this may not be released by the end of the
3105 // scope above. Adding a manual shutdown so that future changes to the fence
3106 // waiter will not flake this test.
3107 context->Shutdown();
3108
3109 // The texture should be released by now.
3110 ASSERT_TRUE(weak_texture.expired()) << "When the texture is no longer in use "
3111 "by the backend, it should be "
3112 "released.";
3113 }

References impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::ColorSource::MakeImage(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [186/419]

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

Definition at line 20 of file aiks_path_unittests.cc.

20 {
21 Canvas canvas;
22 canvas.Concat(Matrix::MakeTranslation({300, 300}));
23 canvas.Concat(Matrix::MakeRotationZ(Radians(kPiOver2)));
24 auto arrow_stem =
25 PathBuilder{}.MoveTo({120, 190}).LineTo({120, 50}).TakePath();
26 auto arrow_head = PathBuilder{}
27 .MoveTo({50, 120})
28 .LineTo({120, 190})
29 .LineTo({190, 120})
30 .TakePath();
31 auto paint = Paint{
32 .stroke_width = 15.0,
33 .stroke_cap = Cap::kRound,
34 .stroke_join = Join::kRound,
35 .style = Paint::Style::kStroke,
36 .color_filter =
37 ColorFilter::MakeBlend(BlendMode::kSourceIn, Color::AliceBlue()),
38 };
39
40 canvas.DrawPath(arrow_stem, paint);
41 canvas.DrawPath(arrow_head, paint);
42 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
43 }

References impeller::Color::AliceBlue(), impeller::Canvas::Concat(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::kPiOver2, impeller::kRound, impeller::kSourceIn, impeller::Paint::kStroke, impeller::LineTo(), impeller::ColorFilter::MakeBlend(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeTranslation(), impeller::PathBuilder::MoveTo(), and impeller::Paint::stroke_width.

## ◆ TEST_P() [187/419]

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

Definition at line 1746 of file aiks_unittests.cc.

1746 {
1747 // Compare with https://fiddle.skia.org/c/9e03de8567ffb49e7e83f53b64bcf636
1748 Canvas canvas;
1749 Paint paint;
1750
1751 paint.color = Color::Black();
1752 Rect rect = Rect::MakeXYWH(25, 25, 25, 25);
1753 canvas.DrawRect(rect, paint);
1754
1755 canvas.Translate({10, 10});
1756 canvas.SaveLayer({});
1757
1758 paint.color = Color::Green();
1759 canvas.DrawRect(rect, paint);
1760
1761 canvas.Restore();
1762
1763 canvas.Translate({10, 10});
1764 paint.color = Color::Red();
1765 canvas.DrawRect(rect, paint);
1766
1767 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1768 }

References impeller::Color::Black(), impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [188/419]

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

Definition at line 1827 of file aiks_unittests.cc.

1827 {
1828 Canvas canvas;
1829 canvas.Scale(GetContentScale());
1830 canvas.Translate(Vector2(100, 100));
1831
1832 auto texture = std::make_shared<Image>(CreateTextureForFixture("boston.jpg"));
1833 auto draw_image_layer = [&canvas, &texture](const Paint& paint) {
1834 canvas.SaveLayer(paint);
1835 canvas.DrawImage(texture, {}, Paint{});
1836 canvas.Restore();
1837 };
1838
1839 Paint effect_paint;
1840 effect_paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
1841 .style = FilterContents::BlurStyle::kNormal,
1842 .sigma = Sigma{6},
1843 };
1844 draw_image_layer(effect_paint);
1845
1846 canvas.Translate(Vector2(300, 300));
1847 canvas.Scale(Vector2(3, 3));
1848 draw_image_layer(effect_paint);
1849
1850 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1851 }

References impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::FilterContents::kNormal, impeller::Paint::mask_blur_descriptor, impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Canvas::Translate().

## ◆ TEST_P() [189/419]

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

Definition at line 1770 of file aiks_unittests.cc.

1770 {
1771 Canvas canvas;
1772 Paint paint;
1773 Rect rect = Rect::MakeXYWH(0, 0, 1000, 1000);
1774
1775 // Black, green, and red squares offset by [10, 10].
1776 {
1777 canvas.SaveLayer({}, Rect::MakeXYWH(25, 25, 25, 25));
1778 paint.color = Color::Black();
1779 canvas.DrawRect(rect, paint);
1780 canvas.Restore();
1781 }
1782
1783 {
1784 canvas.SaveLayer({}, Rect::MakeXYWH(35, 35, 25, 25));
1785 paint.color = Color::Green();
1786 canvas.DrawRect(rect, paint);
1787 canvas.Restore();
1788 }
1789
1790 {
1791 canvas.SaveLayer({}, Rect::MakeXYWH(45, 45, 25, 25));
1792 paint.color = Color::Red();
1793 canvas.DrawRect(rect, paint);
1794 canvas.Restore();
1795 }
1796
1797 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1798 }

References impeller::Color::Black(), impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [190/419]

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

Definition at line 2987 of file aiks_unittests.cc.

2987 {
2988 auto contents = SolidColorContents();
2989 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.75));
2990 auto result = contents.ApplyColorFilter([](const Color& color) {
2991 return color.Blend(Color::LimeGreen().WithAlpha(0.75), BlendMode::kScreen);
2992 });
2993 ASSERT_TRUE(result);
2994 ASSERT_COLOR_NEAR(contents.GetColor(),
2995 Color(0.424452, 0.828743, 0.79105, 0.9375));
2996 }

References ASSERT_COLOR_NEAR, impeller::Color::Blend(), impeller::Color::CornflowerBlue(), impeller::kScreen, and impeller::Color::LimeGreen().

## ◆ TEST_P() [191/419]

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

Definition at line 1557 of file aiks_unittests.cc.

1557 {
1558 Canvas canvas;
1559 canvas.Scale(GetContentScale());
1560 Paint paint;
1561 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
1562 .style = FilterContents::BlurStyle::kNormal,
1563 .sigma = Sigma{1},
1564 };
1565
1566 canvas.DrawPaint({.color = Color::White()});
1567
1568 paint.color = Color::Crimson();
1569 Scalar y = 100.0f;
1570 for (int i = 0; i < 5; i++) {
1571 Scalar x = (i + 1) * 100;
1572 Scalar radius = x / 10.0f;
1573 canvas.DrawRect(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1574 radius, 60.0f - radius),
1575 paint);
1576 }
1577
1578 paint.color = Color::Blue();
1579 y += 100.0f;
1580 for (int i = 0; i < 5; i++) {
1581 Scalar x = (i + 1) * 100;
1582 Scalar radius = x / 10.0f;
1583 canvas.DrawCircle({x + 25, y + 25}, radius, paint);
1584 }
1585
1586 paint.color = Color::Green();
1587 y += 100.0f;
1588 for (int i = 0; i < 5; i++) {
1589 Scalar x = (i + 1) * 100;
1590 Scalar radius = x / 10.0f;
1591 canvas.DrawOval(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1592 radius, 60.0f - radius),
1593 paint);
1594 }
1595
1596 paint.color = Color::Purple();
1597 y += 100.0f;
1598 for (int i = 0; i < 5; i++) {
1599 Scalar x = (i + 1) * 100;
1600 Scalar radius = x / 20.0f;
1601 canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
1602 {radius, radius}, //
1603 paint);
1604 }
1605
1606 paint.color = Color::Orange();
1607 y += 100.0f;
1608 for (int i = 0; i < 5; i++) {
1609 Scalar x = (i + 1) * 100;
1610 Scalar radius = x / 20.0f;
1611 canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
1612 {radius, 5.0f}, paint);
1613 }
1614
1615 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1616 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Color::Crimson(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawOval(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kNormal, impeller::TRect< Scalar >::MakeXYWH(), impeller::Paint::mask_blur_descriptor, impeller::Color::Orange(), impeller::Color::Purple(), impeller::Canvas::Scale(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Color::White().

## ◆ TEST_P() [192/419]

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

Definition at line 181 of file aiks_path_unittests.cc.

181 {
182 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
183 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
184 static Color color = Color::Black().WithAlpha(0.5);
185 static float scale = 3;
186 static bool add_circle_clip = true;
187
188 if (AiksTest::ImGuiBegin("Controls", nullptr,
189 ImGuiWindowFlags_AlwaysAutoResize)) {
190 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
191 ImGui::SliderFloat("Scale", &scale, 0, 6);
192 ImGui::Checkbox("Circle clip", &add_circle_clip);
193 ImGui::End();
194 }
195
196 Canvas canvas;
197 canvas.Scale(GetContentScale());
198 Paint paint;
199
200 paint.color = Color::White();
201 canvas.DrawPaint(paint);
202
203 paint.color = color;
204 paint.style = Paint::Style::kStroke;
205 paint.stroke_width = 10;
206
207 Path path = PathBuilder{}
208 .MoveTo({20, 20})
209 .QuadraticCurveTo({60, 20}, {60, 60})
210 .Close()
211 .MoveTo({60, 20})
212 .QuadraticCurveTo({60, 60}, {20, 60})
213 .TakePath();
214
215 canvas.Scale(Vector2(scale, scale));
216
217 if (add_circle_clip) {
218 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
219 Color::Red());
220 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
221 Color::Red());
222 auto [handle_a, handle_b] =
223 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
224
225 auto screen_to_canvas = canvas.GetCurrentTransform().Invert();
226 Point point_a = screen_to_canvas * handle_a * GetContentScale();
227 Point point_b = screen_to_canvas * handle_b * GetContentScale();
228
229 Point middle = (point_a + point_b) / 2;
230 auto radius = point_a.GetDistance(middle);
231 canvas.ClipPath(PathBuilder{}.AddCircle(middle, radius).TakePath());
232 }
233
234 for (auto join : {Join::kBevel, Join::kRound, Join::kMiter}) {
235 paint.stroke_join = join;
236 for (auto cap : {Cap::kButt, Cap::kSquare, Cap::kRound}) {
237 paint.stroke_cap = cap;
238 canvas.DrawPath(path, paint);
239 canvas.Translate({80, 0});
240 }
241 canvas.Translate({-240, 60});
242 }
243
244 return canvas.EndRecordingAsPicture();
245 };
246
247 ASSERT_TRUE(OpenPlaygroundHere(callback));
248 }

References impeller::PathBuilder::AddCircle(), impeller::Color::Black(), impeller::Canvas::ClipPath(), impeller::Close(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::DrawPlaygroundLine(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::GetCurrentTransform(), impeller::TPoint< T >::GetDistance(), impeller::AiksPlayground::ImGuiBegin(), impeller::Matrix::Invert(), impeller::kBevel, impeller::kButt, impeller::kMiter, impeller::kRound, impeller::kSquare, impeller::Paint::kStroke, impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Canvas::Scale(), scale, impeller::Paint::stroke_cap, impeller::Paint::stroke_join, impeller::Paint::stroke_width, impeller::Paint::style, impeller::PathBuilder::TakePath(), impeller::Canvas::Translate(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [193/419]

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

Definition at line 2219 of file aiks_unittests.cc.

2219 {
2220 Canvas canvas;
2221
2222 canvas.SaveLayer({
2223 .color_filter = ColorFilter::MakeSrgbToLinear(),
2224 });
2225
2226 canvas.Translate({500, 300, 0});
2227 canvas.Rotate(Radians(2 * kPi / 3));
2228 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
2229
2230 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2231 }

References impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kPi, impeller::ColorFilter::MakeSrgbToLinear(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Rotate(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [194/419]

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

Definition at line 1339 of file aiks_unittests.cc.

1339 {
1340 Canvas canvas;
1341 canvas.Scale(GetContentScale());
1342 Paint paint;
1343 const int color_count = 3;
1344 Color colors[color_count] = {
1345 Color::Blue(),
1346 Color::Green(),
1347 Color::Crimson(),
1348 };
1349
1350 paint.color = Color::White();
1351 canvas.DrawPaint(paint);
1352
1353 int c_index = 0;
1354
1355 auto draw = [&paint, &colors, &c_index](Canvas& canvas, Point center,
1356 Scalar r, Scalar dr, int n) {
1357 for (int i = 0; i < n; i++) {
1358 paint.color = colors[(c_index++) % color_count];
1359 canvas.DrawCircle(center, r, paint);
1360 r += dr;
1361 }
1362 };
1363
1364 paint.style = Paint::Style::kStroke;
1365 paint.stroke_width = 1;
1366 draw(canvas, {10, 10}, 2, 2, 14); // r = [2, 28], covers [1,29]
1367 paint.stroke_width = 5;
1368 draw(canvas, {10, 10}, 35, 10, 56); // r = [35, 585], covers [30,590]
1369
1370 std::vector<Color> gradient_colors = {
1371 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1372 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1373 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1374 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1375 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1376 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1377 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1378 std::vector<Scalar> stops = {
1379 0.0,
1380 (1.0 / 6.0) * 1,
1381 (1.0 / 6.0) * 2,
1382 (1.0 / 6.0) * 3,
1383 (1.0 / 6.0) * 4,
1384 (1.0 / 6.0) * 5,
1385 1.0,
1386 };
1387 auto texture = CreateTextureForFixture("airplane.jpg",
1388 /*enable_mipmapping=*/true);
1389
1390 paint.color_source = ColorSource::MakeRadialGradient(
1391 {500, 600}, 75, std::move(gradient_colors), std::move(stops),
1392 Entity::TileMode::kMirror, {});
1393 draw(canvas, {500, 600}, 5, 10, 10);
1394
1395 paint.color_source = ColorSource::MakeImage(
1396 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1397 Matrix::MakeTranslation({700, 200}));
1398 draw(canvas, {800, 300}, 5, 10, 10);
1399
1400 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1401 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Paint::color_source, impeller::Color::Crimson(), impeller::Canvas::DrawPaint(), impeller::Color::Green(), impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::Paint::kStroke, impeller::ColorSource::MakeImage(), impeller::ColorSource::MakeRadialGradient(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Scale(), impeller::Paint::stroke_width, impeller::Paint::style, and impeller::Color::White().

## ◆ TEST_P() [195/419]

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

Definition at line 3265 of file aiks_unittests.cc.

3265 {
3266 Canvas canvas;
3267
3268 // Use a non-srcOver blend mode to ensure that we don't detect this as an
3269 // opacity peephole optimization.
3270 canvas.SaveLayer(
3271 {.color = Color::Blue().WithAlpha(0.5), .blend_mode = BlendMode::kSource},
3272 Rect::MakeLTRB(0, 0, 200, 200));
3273 canvas.DrawPaint(
3274 {.color = Color::BlackTransparent(), .blend_mode = BlendMode::kSource});
3275 canvas.Restore();
3276
3277 canvas.SaveLayer(
3278 {.color = Color::Blue(), .blend_mode = BlendMode::kDestinationOver});
3279 canvas.Restore();
3280
3281 // This playground should appear blank on CI since we are only drawing
3282 // transparent black. If the clear color optimization is broken, the texture
3283 // will be filled with NaNs and may produce a magenta texture on macOS or iOS.
3284 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3285 }

References impeller::Color::BlackTransparent(), impeller::Color::Blue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kDestinationOver, impeller::kSource, impeller::TRect< Scalar >::MakeLTRB(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [196/419]

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

Definition at line 2903 of file aiks_unittests.cc.

2903 {
2904 auto mapping = flutter::testing::OpenFixtureAsSkData("Roboto-Regular.ttf");
2905 ASSERT_NE(mapping, nullptr);
2906
2907 Scalar font_size = 100;
2908 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
2909 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
2910
2911 Paint text_paint;
2912 text_paint.color = Color::Blue();
2913
2914 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
2915 Color{0.1294, 0.5882, 0.9529, 1.0}};
2916 std::vector<Scalar> stops = {
2917 0.0,
2918 1.0,
2919 };
2920 text_paint.color_source = ColorSource::MakeLinearGradient(
2921 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
2922 Entity::TileMode::kRepeat, {});
2923
2924 Canvas canvas;
2925 canvas.Translate({100, 100});
2926 canvas.Rotate(Radians(kPi / 4));
2927
2928 auto blob = SkTextBlob::MakeFromString("Hello", sk_font);
2929 ASSERT_NE(blob, nullptr);
2930 auto frame = MakeTextFrameFromTextBlobSkia(blob);
2931 canvas.DrawTextFrame(frame, Point(), text_paint);
2932
2933 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2934 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Paint::color_source, impeller::kPi, impeller::Entity::kRepeat, impeller::ColorSource::MakeLinearGradient(), impeller::MakeTextFrameFromTextBlobSkia(), and impeller::Canvas::Translate().

## ◆ TEST_P() [197/419]

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

Definition at line 801 of file aiks_unittests.cc.

801 {
802 // "Random" numbers between 0 and 1. Hardcoded to avoid flakiness in goldens.
803 std::array<Scalar, 20> phase_offsets = {
804 7.82637e-06, 0.131538, 0.755605, 0.45865, 0.532767,
805 0.218959, 0.0470446, 0.678865, 0.679296, 0.934693,
806 0.383502, 0.519416, 0.830965, 0.0345721, 0.0534616,
807 0.5297, 0.671149, 0.00769819, 0.383416, 0.0668422};
808 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
809 static float font_size = 20;
810 static float phase_variation = 0.2;
811 static float speed = 0.5;
812 static float magnitude = 100;
813 if (AiksTest::ImGuiBegin("Controls", nullptr,
814 ImGuiWindowFlags_AlwaysAutoResize)) {
815 ImGui::SliderFloat("Font size", &font_size, 5, 50);
816 ImGui::SliderFloat("Phase variation", &phase_variation, 0, 1);
817 ImGui::SliderFloat("Oscillation speed", &speed, 0, 2);
818 ImGui::SliderFloat("Oscillation magnitude", &magnitude, 0, 300);
819 ImGui::End();
820 }
821
822 Canvas canvas;
823 canvas.Scale(GetContentScale());
824
825 for (size_t i = 0; i < phase_offsets.size(); i++) {
826 auto position =
827 Point(200 + magnitude *
828 std::sin((-phase_offsets[i] * k2Pi * phase_variation +
829 GetSecondsElapsed() * speed)), //
830 200 + i * font_size * 1.1 //
831 );
832 if (!RenderTextInCanvasSkia(
833 GetContext(), canvas,
834 "the quick brown fox jumped over "
835 "the lazy dog!.?",
836 "Roboto-Regular.ttf",
837 {.font_size = font_size, .position = position})) {
838 return std::nullopt;
839 }
840 }
841 return canvas.EndRecordingAsPicture();
842 };
843
844 ASSERT_TRUE(OpenPlaygroundHere(callback));
845 }

References impeller::Canvas::EndRecordingAsPicture(), impeller::AiksPlayground::ImGuiBegin(), impeller::k2Pi, RenderTextInCanvasSkia(), and impeller::Canvas::Scale().

## ◆ TEST_P() [198/419]

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

Definition at line 956 of file aiks_unittests.cc.

956 {
957 Canvas canvas;
958 canvas.Scale(GetContentScale());
959 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
960
961 canvas.Transform(Matrix(0.25, -0.3, 0, -0.002, //
962 0, 0.5, 0, 0, //
963 0, 0, 0.3, 0, //
964 100, 100, 0, 1.3));
965 ASSERT_TRUE(RenderTextInCanvasSkia(
966 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
967 "Roboto-Regular.ttf"));
968
969 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
970 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), RenderTextInCanvasSkia(), impeller::Canvas::Scale(), and impeller::Canvas::Transform().

## ◆ TEST_P() [199/419]

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

Definition at line 1241 of file aiks_unittests.cc.

1241 {
1242 Canvas canvas;
1243 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(), Matrix());
1244
1245 // clang-format off
1246 canvas.Translate(Vector3(100, 200));
1247 ASSERT_MATRIX_NEAR(
1248 canvas.GetCurrentTransform(),
1249 Matrix( 1, 0, 0, 0,
1250 0, 1, 0, 0,
1251 0, 0, 1, 0,
1252 100, 200, 0, 1));
1253
1254 canvas.Rotate(Radians(kPiOver2));
1255 ASSERT_MATRIX_NEAR(
1256 canvas.GetCurrentTransform(),
1257 Matrix( 0, 1, 0, 0,
1258 -1, 0, 0, 0,
1259 0, 0, 1, 0,
1260 100, 200, 0, 1));
1261
1262 canvas.Scale(Vector3(2, 3));
1263 ASSERT_MATRIX_NEAR(
1264 canvas.GetCurrentTransform(),
1265 Matrix( 0, 2, 0, 0,
1266 -3, 0, 0, 0,
1267 0, 0, 0, 0,
1268 100, 200, 0, 1));
1269
1270 canvas.Translate(Vector3(100, 200));
1271 ASSERT_MATRIX_NEAR(
1272 canvas.GetCurrentTransform(),
1273 Matrix( 0, 2, 0, 0,
1274 -3, 0, 0, 0,
1275 0, 0, 0, 0,
1276 -500, 400, 0, 1));
1277 // clang-format on
1278 }

References ASSERT_MATRIX_NEAR, impeller::Canvas::GetCurrentTransform(), impeller::kPiOver2, impeller::Canvas::Rotate(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [200/419]

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

Definition at line 2357 of file aiks_unittests.cc.

2357 {
2358 Canvas canvas;
2359
2360 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
2361
2362 canvas.SaveLayer({.color = Color::Black().WithAlpha(0.5)});
2363 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
2364 canvas.Restore();
2365
2366 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2367 }

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [201/419]

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

Definition at line 2530 of file aiks_unittests.cc.

2530 {
2531 Canvas canvas;
2532
2533 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2534 canvas.DrawImage(image, {100, 100}, {});
2535
2536 canvas.SaveLayer({.color = Color::Black().WithAlpha(0.5)});
2537 canvas.DrawImage(image, {100, 500}, {});
2538 canvas.Restore();
2539
2540 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2541 }

References impeller::Color::Black(), impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [202/419]

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

Definition at line 2614 of file aiks_unittests.cc.

2614 {
2615 Canvas canvas;
2616 canvas.DrawRect(Rect::MakeXYWH(0, 0, 400, 400), {.color = Color::Red()});
2617 canvas.SaveLayer({
2618 .color = Color::Black().WithAlpha(0.5),
2619 .blend_mode = BlendMode::kLighten,
2620 });
2621 canvas.DrawCircle({200, 200}, 100, {.color = Color::Green()});
2622 canvas.Restore();
2623 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2624 }

References impeller::Color::Black(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::kLighten, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [203/419]

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

Definition at line 2369 of file aiks_unittests.cc.

2369 {
2370 Canvas canvas;
2371
2372 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
2373
2374 canvas.SaveLayer({
2375 .color = Color::Black().WithAlpha(0.5),
2376 .color_filter =
2377 ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red()),
2378 });
2379 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
2380 canvas.Restore();
2381
2382 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2383 }

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kDestinationOver, impeller::ColorFilter::MakeBlend(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [204/419]

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

Definition at line 2385 of file aiks_unittests.cc.

2385 {
2386 Canvas canvas;
2387
2388 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
2389
2390 canvas.SaveLayer({
2391 .color = Color::Black().WithAlpha(0.5),
2392 .image_filter = ImageFilter::MakeFromColorFilter(
2393 *ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red())),
2394 });
2395
2396 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
2397 canvas.Restore();
2398
2399 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2400 }

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kDestinationOver, impeller::ColorFilter::MakeBlend(), impeller::ImageFilter::MakeFromColorFilter(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [205/419]

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

Definition at line 2402 of file aiks_unittests.cc.

2402 {
2403 Canvas canvas;
2404
2405 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
2406
2407 canvas.SaveLayer({
2408 .color = Color::Black().WithAlpha(0.5),
2409 .color_filter =
2410 ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red()),
2411 });
2412
2413 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
2414 canvas.Restore();
2415
2416 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2417 }

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kDestinationOver, impeller::ColorFilter::MakeBlend(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [206/419]

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

Definition at line 2588 of file aiks_unittests.cc.

2589 {
2590 Canvas canvas;
2591
2592 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2593 canvas.DrawImage(image, {100, 100}, {});
2594
2595 canvas.SaveLayer({
2596 .color = Color::Black().WithAlpha(0.5),
2597 .image_filter = ImageFilter::MakeFromColorFilter(
2598 *ColorFilter::MakeMatrix({.array =
2599 {
2600 1, 0, 0, 0, 0, //
2601 0, 1, 0, 0, 0, //
2602 0, 0.2, 1, 0, 0, //
2603 0, 0, 0, 0.5, 0 //
2604 }})),
2605 .color_filter =
2606 ColorFilter::MakeBlend(BlendMode::kModulate, Color::Green()),
2607 });
2608 canvas.DrawImage(image, {100, 500}, {});
2609 canvas.Restore();
2610
2611 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2612 }

References impeller::Color::Black(), impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::kModulate, impeller::ColorFilter::MakeBlend(), impeller::ImageFilter::MakeFromColorFilter(), impeller::ColorFilter::MakeMatrix(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [207/419]

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

Definition at line 2543 of file aiks_unittests.cc.

2543 {
2544 Canvas canvas;
2545
2546 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2547 canvas.DrawImage(image, {100, 100}, {});
2548
2549 canvas.SaveLayer({
2550 .color = Color::Black().WithAlpha(0.5),
2551 .color_filter = ColorFilter::MakeMatrix({.array =
2552 {
2553 1, 0, 0, 0, 0, //
2554 0, 1, 0, 0, 0, //
2555 0, 0, 1, 0, 0, //
2556 0, 0, 0, 2, 0 //
2557 }}),
2558 });
2559 canvas.DrawImage(image, {100, 500}, {});
2560 canvas.Restore();
2561
2562 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2563 }

References impeller::Color::Black(), impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::ColorFilter::MakeMatrix(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [208/419]

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

Definition at line 2565 of file aiks_unittests.cc.

2565 {
2566 Canvas canvas;
2567
2568 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2569 canvas.DrawImage(image, {100, 100}, {});
2570
2571 canvas.SaveLayer({
2572 .color = Color::Black().WithAlpha(0.5),
2573 .image_filter = ImageFilter::MakeFromColorFilter(
2574 *ColorFilter::MakeMatrix({.array =
2575 {
2576 1, 0, 0, 0, 0, //
2577 0, 1, 0, 0, 0, //
2578 0, 0, 1, 0, 0, //
2579 0, 0, 0, 2, 0 //
2580 }})),
2581 });
2582 canvas.DrawImage(image, {100, 500}, {});
2583 canvas.Restore();
2584
2585 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2586 }

References impeller::Color::Black(), impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::ImageFilter::MakeFromColorFilter(), impeller::ColorFilter::MakeMatrix(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [209/419]

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

Definition at line 3116 of file aiks_unittests.cc.

3116 {
3117 Canvas canvas;
3118 Paint paint;
3119 auto texture = CreateTextureForFixture("table_mountain_nx.png");
3120
3121 paint.color_source = ColorSource::MakeImage(texture, Entity::TileMode::kClamp,
3122 Entity::TileMode::kClamp, {}, {});
3123
3124 auto vertices = {Point(0, 0), Point(texture->GetSize().width, 0),
3125 Point(0, texture->GetSize().height)};
3126 std::vector<uint16_t> indices = {0u, 1u, 2u};
3127 std::vector<Point> texture_coordinates = {};
3128 std::vector<Color> vertex_colors = {};
3129 auto geometry = std::make_shared<VerticesGeometry>(
3130 vertices, indices, texture_coordinates, vertex_colors,
3131 Rect::MakeLTRB(0, 0, 1, 1), VerticesGeometry::VertexMode::kTriangleStrip);
3132
3133 canvas.DrawVertices(geometry, BlendMode::kSourceOver, paint);
3134 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3135 }

References impeller::Paint::color_source, impeller::Canvas::DrawVertices(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::kSourceOver, impeller::VerticesGeometry::kTriangleStrip, impeller::ColorSource::MakeImage(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [210/419]

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

Definition at line 3138 of file aiks_unittests.cc.

3138 {
3139 Canvas canvas;
3140 Paint paint;
3141 auto texture = CreateTextureForFixture("table_mountain_nx.png");
3142
3143 paint.color_source = ColorSource::MakeImage(
3144 texture, Entity::TileMode::kClamp, Entity::TileMode::kClamp, {},
3145 Matrix::MakeTranslation({100.0, 100.0}));
3146
3147 auto vertices = {Point(0, 0), Point(texture->GetSize().width, 0),
3148 Point(0, texture->GetSize().height)};
3149 std::vector<uint16_t> indices = {0u, 1u, 2u};
3150 std::vector<Point> texture_coordinates = {};
3151 std::vector<Color> vertex_colors = {};
3152 auto geometry = std::make_shared<VerticesGeometry>(
3153 vertices, indices, texture_coordinates, vertex_colors,
3154 Rect::MakeLTRB(0, 0, 1, 1), VerticesGeometry::VertexMode::kTriangleStrip);
3155
3156 canvas.DrawVertices(geometry, BlendMode::kSourceOver, paint);
3157 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3158 }

References impeller::Paint::color_source, impeller::Canvas::DrawVertices(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::kSourceOver, impeller::VerticesGeometry::kTriangleStrip, impeller::ColorSource::MakeImage(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [211/419]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitAcrossDifferentPixelFormatsFails |
| ) |  |

Definition at line 18 of file blit_pass_unittests.cc.

18 {
19 ScopedValidationDisable scope; // avoid noise in output.
20 auto context = GetContext();
21 auto cmd_buffer = context->CreateCommandBuffer();
22 auto blit_pass = cmd_buffer->CreateBlitPass();
23
24 TextureDescriptor src_desc;
25 src_desc.format = PixelFormat::kA8UNormInt;
26 src_desc.size = {100, 100};
27 src_desc.storage_mode = StorageMode::kHostVisible;
28 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
29
30 TextureDescriptor dst_format;
31 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
32 dst_format.size = {100, 100};
33 dst_format.storage_mode = StorageMode::kHostVisible;
34 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
35
36 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
37 }

References impeller::TextureDescriptor::format, impeller::kA8UNormInt, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [212/419]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitAcrossDifferentSampleCountsFails |
| ) |  |

Definition at line 39 of file blit_pass_unittests.cc.

39 {
40 ScopedValidationDisable scope; // avoid noise in output.
41 auto context = GetContext();
42 auto cmd_buffer = context->CreateCommandBuffer();
43 auto blit_pass = cmd_buffer->CreateBlitPass();
44
45 TextureDescriptor src_desc;
46 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
47 src_desc.sample_count = SampleCount::kCount4;
48 src_desc.size = {100, 100};
49 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
50
51 TextureDescriptor dst_format;
52 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
53 dst_format.size = {100, 100};
54 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
55
56 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
57 }

References impeller::TextureDescriptor::format, impeller::kCount4, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::sample_count, and impeller::TextureDescriptor::size.

## ◆ TEST_P() [213/419]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitPassesForMatchingFormats |
| ) |  |

Definition at line 59 of file blit_pass_unittests.cc.

59 {
60 ScopedValidationDisable scope; // avoid noise in output.
61 auto context = GetContext();
62 auto cmd_buffer = context->CreateCommandBuffer();
63 auto blit_pass = cmd_buffer->CreateBlitPass();
64
65 TextureDescriptor src_desc;
66 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
67 src_desc.size = {100, 100};
68 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
69
70 TextureDescriptor dst_format;
71 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
72 dst_format.size = {100, 100};
73 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
74
75 EXPECT_TRUE(blit_pass->AddCopy(src, dst));
76 }

References impeller::TextureDescriptor::format, impeller::kR8G8B8A8UNormInt, and impeller::TextureDescriptor::size.

## ◆ TEST_P() [214/419]

impeller::testing::TEST_P | ( | ComputeSubgroupTest | ,
|  | CapabilitiesSuportSubgroups |
| ) |  |

Definition at line 42 of file compute_subgroup_unittests.cc.

42 {
43 auto context = GetContext();
44 ASSERT_TRUE(context);
45 ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
46 }

## ◆ TEST_P() [215/419]

impeller::testing::TEST_P | ( | ComputeSubgroupTest | ,
|  | LargePath |
| ) |  |

Definition at line 173 of file compute_subgroup_unittests.cc.

173 {
174 // The path in here is large enough to highlight issues around exceeding
175 // subgroup size.
176 using SS = StrokeComputeShader;
177
178 auto context = GetContext();
179 ASSERT_TRUE(context);
180 ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
181 size_t vertex_count = 0;
182 Scalar stroke_width = 1.0;
183
184 auto vertex_buffer = CreateHostVisibleDeviceBuffer<SS::VertexBuffer<2048>>(
185 context, "VertexBuffer");
186 auto vertex_buffer_count =
187 CreateHostVisibleDeviceBuffer<SS::VertexBufferCount>(context,
188 "VertexCount");
189
190 auto complex_path =
191 PathBuilder{}
192 .MoveTo({359.934, 96.6335})
193 .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
194 {354.673, 96.8895})
195 .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
196 {354.367, 96.9075})
197 .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
198 {349.259, 97.2355})
199 .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
200 {348.625, 97.2834})
201 .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
202 {343.789, 97.6722})
203 .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
204 {342.703, 97.7734})
205 .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
206 {338.246, 98.207})
207 .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
208 {336.612, 98.3894})
209 .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
210 {332.623, 98.8476})
211 .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
212 {332.237, 98.8982})
213 .LineTo({332.237, 102.601})
214 .LineTo({321.778, 102.601})
215 .LineTo({321.778, 100.382})
216 .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
217 {321.161, 100.476})
218 .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
219 {315.332, 101.479})
220 .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
221 {315.301, 101.484})
222 .LineTo({310.017, 105.94})
223 .LineTo({309.779, 105.427})
224 .LineTo({314.403, 101.651})
225 .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
226 {314.368, 101.658})
227 .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
228 {308.846, 102.748})
229 .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
230 .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
231 {303.425, 103.936})
232 .LineTo({299.105, 107.578})
233 .LineTo({298.867, 107.065})
234 .LineTo({302.394, 104.185})
235 .LineTo({302.412, 104.171})
236 .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
237 {299.344, 104.921})
238 .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
239 .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
240 {291.462, 106.979})
241 .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
242 {290.471, 107.257})
243 .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
244 {287.449, 108.139})
245 .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
246 {284.536, 109.035})
247 .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
248 {281.952, 109.859})
249 .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
250 {279.633, 110.638})
251 .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
252 {276.803, 111.607})
253 .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
254 {276.672, 111.653})
255 .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
256 {271.721, 113.463})
257 .LineTo({271.717, 113.449})
258 .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
259 {270.963, 113.628})
260 .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
261 {270.748, 113.682})
262 .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
263 {269.839, 113.926})
264 .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
265 {269.681, 113.972})
266 .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
267 {268.756, 114.239})
268 .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
269 {268.367, 114.354})
270 .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
271 {267.752, 114.54})
272 .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
273 {253.564, 119.252})
274 .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
275 {253.538, 119.261})
276 .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
277 {248.189, 121.131})
278 .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
279 .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
280 {245.975, 121.912})
281 .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
282 {244.698, 122.364})
283 .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
284 {242.794, 123.04})
285 .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
286 {240.961, 123.693})
287 .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
288 {240.052, 124.018})
289 .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
290 .LineTo({237.164, 125.003})
291 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
292 {235.81, 125.538})
293 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
294 {234.592, 125.977})
295 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
296 {234.59, 125.977})
297 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
298 {192.381, 141.429})
299 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
300 .LineTo({360, 160})
301 .LineTo({360, 119.256})
302 .LineTo({360, 106.332})
303 .LineTo({360, 96.6307})
304 .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
305 {359.934, 96.6335})
306 .Close()
307 .TakePath();
308
309 auto callback = [&](RenderPass& pass) -> bool {
310 ::memset(vertex_buffer_count->OnGetContents(), 0,
311 sizeof(SS::VertexBufferCount));
312 ::memset(vertex_buffer->OnGetContents(), 0, sizeof(SS::VertexBuffer<2048>));
313
314 ContentContext renderer(context, nullptr);
315 if (!renderer.IsValid()) {
316 return false;
317 }
318
319 ComputeTessellator{}
320 .SetStrokeWidth(stroke_width)
321 .Tessellate(
322 complex_path, renderer.GetTransientsBuffer(), context,
323 DeviceBuffer::AsBufferView(vertex_buffer),
324 DeviceBuffer::AsBufferView(vertex_buffer_count),
325 [vertex_buffer_count, &vertex_count](CommandBuffer::Status status) {
326 vertex_count = reinterpret_cast<SS::VertexBufferCount*>(
327 vertex_buffer_count->OnGetContents())
328 ->count;
329 });
330
331 using VS = SolidFillPipeline::VertexShader;
332
333 pass.SetCommandLabel("Draw Stroke");
334 pass.SetStencilReference(0);
335
336 ContentContextOptions options;
337 options.sample_count = pass.GetRenderTarget().GetSampleCount();
338 options.color_attachment_pixel_format =
339 pass.GetRenderTarget().GetRenderTargetPixelFormat();
340 options.has_depth_stencil_attachments =
341 pass.GetRenderTarget().GetStencilAttachment().has_value();
342 options.blend_mode = BlendMode::kSourceIn;
343 options.primitive_type = PrimitiveType::kTriangleStrip;
344
345 options.stencil_mode =
346 ContentContextOptions::StencilMode::kLegacyClipIncrement;
347
348 pass.SetPipeline(renderer.GetSolidFillPipeline(options));
349
350 auto count = reinterpret_cast<SS::VertexBufferCount*>(
351 vertex_buffer_count->OnGetContents())
352 ->count;
353
354 pass.SetVertexBuffer(
355 VertexBuffer{.vertex_buffer = DeviceBuffer::AsBufferView(vertex_buffer),
356 .vertex_count = count,
357 .index_type = IndexType::kNone});
358
359 VS::FrameInfo frame_info;
360 auto world_matrix = Matrix::MakeScale(GetContentScale());
361 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
362 frame_info.color = Color::Red().Premultiply();
363 VS::BindFrameInfo(
364 pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info));
365
366 return pass.Draw().ok();
367 };
368 ASSERT_TRUE(OpenPlaygroundHere(callback));
369 }

References impeller::DeviceBuffer::AsBufferView(), impeller::ContentContextOptions::blend_mode, impeller::Close(), impeller::ContentContextOptions::color_attachment_pixel_format, impeller::HostBuffer::EmplaceUniform(), impeller::ContentContext::GetSolidFillPipeline(), impeller::ContentContext::GetTransientsBuffer(), impeller::ContentContextOptions::has_depth_stencil_attachments, impeller::ContentContext::IsValid(), impeller::ContentContextOptions::kLegacyClipIncrement, impeller::kNone, impeller::kSourceIn, impeller::kTriangleStrip, impeller::LineTo(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Premultiply(), impeller::ContentContextOptions::primitive_type, impeller::Color::Red(), impeller::ContentContextOptions::sample_count, impeller::ComputeTessellator::SetStrokeWidth(), impeller::ContentContextOptions::stencil_mode, stroke_width, impeller::ComputeTessellator::Tessellate(), and impeller::VertexBuffer::vertex_buffer.

## ◆ TEST_P() [216/419]

impeller::testing::TEST_P | ( | ComputeSubgroupTest | ,
|  | PathPlayground |
| ) |  |

Definition at line 48 of file compute_subgroup_unittests.cc.

48 {
49 // Renders stroked SVG paths in an interactive playground.
50 using SS = StrokeComputeShader;
51
52 auto context = GetContext();
53 ASSERT_TRUE(context);
54 ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
55 char svg_path_data[16384] =
56 "M140 20 "
57 "C73 20 20 74 20 140 "
58 "c0 135 136 170 228 303 "
59 "88-132 229-173 229-303 "
60 "0-66-54-120-120-120 "
61 "-48 0-90 28-109 69 "
62 "-19-41-60-69-108-69z";
63 size_t vertex_count = 0;
64 Scalar stroke_width = 1.0;
65
66 auto vertex_buffer = CreateHostVisibleDeviceBuffer<SS::VertexBuffer<2048>>(
67 context, "VertexBuffer");
68 auto vertex_buffer_count =
69 CreateHostVisibleDeviceBuffer<SS::VertexBufferCount>(context,
70 "VertexCount");
71
72 auto callback = [&](RenderPass& pass) -> bool {
73 ::memset(vertex_buffer_count->OnGetContents(), 0,
74 sizeof(SS::VertexBufferCount));
75 ::memset(vertex_buffer->OnGetContents(), 0, sizeof(SS::VertexBuffer<2048>));
76 const auto* main_viewport = ImGui::GetMainViewport();
77 ImGui::SetNextWindowPos(
78 ImVec2(main_viewport->WorkPos.x + 650, main_viewport->WorkPos.y + 20));
79 ImGui::Begin("Path data", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
80 ImGui::InputTextMultiline("Path", svg_path_data,
81 IM_ARRAYSIZE(svg_path_data));
82 ImGui::DragFloat("Stroke width", &stroke_width, .1, 0.0, 25.0);
83
84 SkPath sk_path;
85 if (SkParsePath::FromSVGString(svg_path_data, &sk_path)) {
86 std::promise<bool> promise;
87 auto future = promise.get_future();
88
89 auto path = skia_conversions::ToPath(sk_path);
90 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
91 auto status =
92 ComputeTessellator{}
93 .SetStrokeWidth(stroke_width)
94 .Tessellate(path, *host_buffer, context,
95 DeviceBuffer::AsBufferView(vertex_buffer),
96 DeviceBuffer::AsBufferView(vertex_buffer_count),
97 [vertex_buffer_count, &vertex_count,
98 &promise](CommandBuffer::Status status) {
99 vertex_count =
100 reinterpret_cast<SS::VertexBufferCount*>(
101 vertex_buffer_count->OnGetContents())
102 ->count;
103 promise.set_value(
104 status == CommandBuffer::Status::kCompleted);
105 });
106 switch (status) {
107 case ComputeTessellator::Status::kCommandInvalid:
108 ImGui::Text("Failed to submit compute job (invalid command)");
109 break;
110 case ComputeTessellator::Status::kTooManyComponents:
111 ImGui::Text("Failed to submit compute job (too many components) ");
112 break;
113 case ComputeTessellator::Status::kOk:
114 break;
115 }
116 if (!future.get()) {
117 ImGui::Text("Failed to submit compute job.");
118 return false;
119 }
120 if (vertex_count > 0) {
121 ImGui::Text("Vertex count: %zu", vertex_count);
122 }
123 } else {
124 ImGui::Text("Failed to parse path data");
125 }
126 ImGui::End();
127
128 ContentContext renderer(context, nullptr);
129 if (!renderer.IsValid()) {
130 return false;
131 }
132
133 using VS = SolidFillPipeline::VertexShader;
134
135 pass.SetCommandLabel("Draw Stroke");
136 pass.SetStencilReference(0);
137
138 ContentContextOptions options;
139 options.sample_count = pass.GetRenderTarget().GetSampleCount();
140 options.color_attachment_pixel_format =
141 pass.GetRenderTarget().GetRenderTargetPixelFormat();
142 options.has_depth_stencil_attachments =
143 pass.GetRenderTarget().GetStencilAttachment().has_value();
144 options.blend_mode = BlendMode::kSourceIn;
145 options.primitive_type = PrimitiveType::kTriangleStrip;
146
147 options.stencil_mode =
148 ContentContextOptions::StencilMode::kLegacyClipIncrement;
149
150 pass.SetPipeline(renderer.GetSolidFillPipeline(options));
151
152 auto count = reinterpret_cast<SS::VertexBufferCount*>(
153 vertex_buffer_count->OnGetContents())
154 ->count;
155
156 pass.SetVertexBuffer(
157 VertexBuffer{.vertex_buffer = DeviceBuffer::AsBufferView(vertex_buffer),
158 .vertex_count = count,
159 .index_type = IndexType::kNone});
160
161 VS::FrameInfo frame_info;
162 auto world_matrix = Matrix::MakeScale(GetContentScale());
163 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
164 frame_info.color = Color::Red().Premultiply();
165 VS::BindFrameInfo(
166 pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info));
167
168 return pass.Draw().ok();
169 };
170 ASSERT_TRUE(OpenPlaygroundHere(callback));
171 }

References impeller::DeviceBuffer::AsBufferView(), impeller::ContentContextOptions::blend_mode, impeller::ContentContextOptions::color_attachment_pixel_format, impeller::HostBuffer::Create(), impeller::HostBuffer::EmplaceUniform(), impeller::ContentContext::GetSolidFillPipeline(), impeller::ContentContext::GetTransientsBuffer(), impeller::ContentContextOptions::has_depth_stencil_attachments, impeller::ContentContext::IsValid(), impeller::ComputeTessellator::kCommandInvalid, impeller::CommandBuffer::kCompleted, impeller::ContentContextOptions::kLegacyClipIncrement, impeller::kNone, impeller::ComputeTessellator::kOk, impeller::kSourceIn, impeller::ComputeTessellator::kTooManyComponents, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), impeller::Color::Premultiply(), impeller::ContentContextOptions::primitive_type, impeller::Color::Red(), impeller::ContentContextOptions::sample_count, impeller::ComputeTessellator::SetStrokeWidth(), impeller::ContentContextOptions::stencil_mode, stroke_width, impeller::ComputeTessellator::Tessellate(), impeller::skia_conversions::ToPath(), and impeller::VertexBuffer::vertex_buffer.

## ◆ TEST_P() [217/419]

impeller::testing::TEST_P | ( | ComputeSubgroupTest | ,
|  | QuadAndCubicInOnePath |
| ) |  |

Definition at line 371 of file compute_subgroup_unittests.cc.

371 {
372 using SS = StrokeComputeShader;
373
374 auto context = GetContext();
375 ASSERT_TRUE(context);
376 ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
377
378 auto vertex_buffer = CreateHostVisibleDeviceBuffer<SS::VertexBuffer<2048>>(
379 context, "VertexBuffer");
380 auto vertex_buffer_count =
381 CreateHostVisibleDeviceBuffer<SS::VertexBufferCount>(context,
382 "VertexBufferCount");
383
384 auto path = PathBuilder{}
385 .AddCubicCurve({140, 20}, {73, 20}, {20, 74}, {20, 140})
386 .AddQuadraticCurve({20, 140}, {93, 90}, {100, 42})
387 .TakePath();
388
389 auto tessellator = ComputeTessellator{};
390
391 fml::AutoResetWaitableEvent latch;
392
393 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
394 auto status = tessellator.Tessellate(
395 path, *host_buffer, context, DeviceBuffer::AsBufferView(vertex_buffer),
396 DeviceBuffer::AsBufferView(vertex_buffer_count),
397 [&latch](CommandBuffer::Status status) {
398 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
399 latch.Signal();
400 });
401
402 ASSERT_EQ(status, ComputeTessellator::Status::kOk);
403
404 auto callback = [&](RenderPass& pass) -> bool {
405 ContentContext renderer(context, nullptr);
406 if (!renderer.IsValid()) {
407 return false;
408 }
409
410 using VS = SolidFillPipeline::VertexShader;
411
412 pass.SetCommandLabel("Draw Stroke");
413 pass.SetStencilReference(0);
414
415 ContentContextOptions options;
416 options.sample_count = pass.GetRenderTarget().GetSampleCount();
417 options.color_attachment_pixel_format =
418 pass.GetRenderTarget().GetRenderTargetPixelFormat();
419 options.has_depth_stencil_attachments =
420 pass.GetRenderTarget().GetStencilAttachment().has_value();
421 options.blend_mode = BlendMode::kSourceIn;
422 options.primitive_type = PrimitiveType::kTriangleStrip;
423
424 options.stencil_mode =
425 ContentContextOptions::StencilMode::kLegacyClipIncrement;
426
427 pass.SetPipeline(renderer.GetSolidFillPipeline(options));
428
429 auto count = reinterpret_cast<SS::VertexBufferCount*>(
430 vertex_buffer_count->OnGetContents())
431 ->count;
432
433 pass.SetVertexBuffer(
434 VertexBuffer{.vertex_buffer = DeviceBuffer::AsBufferView(vertex_buffer),
435 .vertex_count = count,
436 .index_type = IndexType::kNone});
437
438 VS::FrameInfo frame_info;
439 auto world_matrix = Matrix::MakeScale(GetContentScale());
440 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
441 frame_info.color = Color::Red().Premultiply();
442 VS::BindFrameInfo(
443 pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info));
444
445 return pass.Draw().ok();
446 };
447 ASSERT_TRUE(OpenPlaygroundHere(callback));
448
449 // The latch is down here because it's expected that on Metal the backend
450 // will take care of synchronizing the buffer between the compute and render
451 // pass usages, since it's not MTLHeap allocated. However, if playgrounds
452 // are disabled, no render pass actually gets submitted and we need to do a
453 // CPU latch here.
454 latch.Wait();
455
456 auto vertex_count = reinterpret_cast<SS::VertexBufferCount*>(
457 vertex_buffer_count->OnGetContents())
458 ->count;
459 EXPECT_EQ(vertex_count, golden_cubic_and_quad_points.size());
460 auto vertex_buffer_data =
461 reinterpret_cast<SS::VertexBuffer<2048>*>(vertex_buffer->OnGetContents());
462 for (size_t i = 0; i < vertex_count; i++) {
463 EXPECT_LT(std::abs(golden_cubic_and_quad_points[i].x -
464 vertex_buffer_data->position[i].x),
465 1e-3);
466 EXPECT_LT(std::abs(golden_cubic_and_quad_points[i].y -
467 vertex_buffer_data->position[i].y),
468 1e-3);
469 }
470 }

References impeller::PathBuilder::AddCubicCurve(), impeller::DeviceBuffer::AsBufferView(), impeller::ContentContextOptions::blend_mode, impeller::ContentContextOptions::color_attachment_pixel_format, impeller::HostBuffer::Create(), impeller::HostBuffer::EmplaceUniform(), impeller::ContentContext::GetSolidFillPipeline(), impeller::ContentContext::GetTransientsBuffer(), golden_cubic_and_quad_points, impeller::ContentContextOptions::has_depth_stencil_attachments, impeller::ContentContext::IsValid(), impeller::CommandBuffer::kCompleted, impeller::ContentContextOptions::kLegacyClipIncrement, impeller::kNone, impeller::ComputeTessellator::kOk, impeller::kSourceIn, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), impeller::Color::Premultiply(), impeller::ContentContextOptions::primitive_type, impeller::Color::Red(), impeller::ContentContextOptions::sample_count, impeller::ContentContextOptions::stencil_mode, and impeller::VertexBuffer::vertex_buffer.

## ◆ TEST_P() [218/419]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | 1DThreadgroupSizingIsCorrect |
| ) |  |

Definition at line 175 of file compute_unittests.cc.

175 {
176 using CS = ThreadgroupSizingTestComputeShader;
177 auto context = GetContext();
178 ASSERT_TRUE(context);
179 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
180
181 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
182 auto pipeline_desc =
183 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
184 ASSERT_TRUE(pipeline_desc.has_value());
185 auto compute_pipeline =
186 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
187 ASSERT_TRUE(compute_pipeline);
188
189 auto cmd_buffer = context->CreateCommandBuffer();
190 auto pass = cmd_buffer->CreateComputePass();
191 ASSERT_TRUE(pass && pass->IsValid());
192
193 static constexpr size_t kCount = 2048;
194
195 pass->SetPipeline(compute_pipeline);
196
197 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
198 context, "Output Buffer");
199
200 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
201
202 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
203 ASSERT_TRUE(pass->EncodeCommands());
204
205 fml::AutoResetWaitableEvent latch;
206 ASSERT_TRUE(
207 context->GetCommandQueue()
208 ->Submit({cmd_buffer},
209 [&latch, output_buffer](CommandBuffer::Status status) {
210 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
211
212 auto view = DeviceBuffer::AsBufferView(output_buffer);
213 EXPECT_EQ(view.range.length,
214 sizeof(CS::OutputData<kCount>));
215
216 CS::OutputData<kCount>* output =
217 reinterpret_cast<CS::OutputData<kCount>*>(
218 output_buffer->OnGetContents());
219 EXPECT_TRUE(output);
220 EXPECT_EQ(output->data[kCount - 1], kCount - 1);
221 latch.Signal();
222 })
223 .ok());
224
225 latch.Wait();
226 }

## ◆ TEST_P() [219/419]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanCompute1DimensionalData |
| ) |  |

Definition at line 373 of file compute_unittests.cc.

373 {
374 using CS = SampleComputeShader;
375 auto context = GetContext();
376 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
377 ASSERT_TRUE(context);
378 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
379
380 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
381 auto pipeline_desc =
382 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
383 ASSERT_TRUE(pipeline_desc.has_value());
384 auto compute_pipeline =
385 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
386 ASSERT_TRUE(compute_pipeline);
387
388 auto cmd_buffer = context->CreateCommandBuffer();
389 auto pass = cmd_buffer->CreateComputePass();
390 ASSERT_TRUE(pass && pass->IsValid());
391
392 static constexpr size_t kCount = 5;
393
394 pass->SetPipeline(compute_pipeline);
395
396 CS::Info info{.count = kCount};
397 CS::Input0<kCount> input_0;
398 CS::Input1<kCount> input_1;
399 for (size_t i = 0; i < kCount; i++) {
400 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
401 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
402 }
403
404 input_0.fixed_array[1] = IPoint32(2, 2);
405 input_1.fixed_array[0] = UintPoint32(3, 3);
406 input_0.some_int = 5;
407 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
408
409 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
410 context, "Output Buffer");
411
412 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
413 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
414 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
415 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
416
417 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
418 ASSERT_TRUE(pass->EncodeCommands());
419
420 fml::AutoResetWaitableEvent latch;
421 ASSERT_TRUE(
422 context->GetCommandQueue()
423 ->Submit(
424 {cmd_buffer},
425 [&latch, output_buffer, &input_0,
426 &input_1](CommandBuffer::Status status) {
427 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
428
429 auto view = DeviceBuffer::AsBufferView(output_buffer);
430 EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
431
432 CS::Output<kCount>* output =
433 reinterpret_cast<CS::Output<kCount>*>(
434 output_buffer->OnGetContents());
435 EXPECT_TRUE(output);
436 for (size_t i = 0; i < kCount; i++) {
437 Vector4 vector = output->elements[i];
438 Vector4 computed = input_0.elements[i] * input_1.elements[i];
439 EXPECT_EQ(vector,
440 Vector4(computed.x + 2 + input_1.some_struct.i,
441 computed.y + 3 + input_1.some_struct.vf.x,
442 computed.z + 5 + input_1.some_struct.vf.y,
443 computed.w));
444 }
445 latch.Signal();
446 })
447 .ok());
448
449 latch.Wait();
450 }

## ◆ TEST_P() [220/419]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanComputePrefixSum |
| ) |  |

Definition at line 109 of file compute_unittests.cc.

109 {
110 using CS = PrefixSumTestComputeShader;
111 auto context = GetContext();
112 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
113 ASSERT_TRUE(context);
114 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
115
116 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
117 auto pipeline_desc =
118 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
119 ASSERT_TRUE(pipeline_desc.has_value());
120 auto compute_pipeline =
121 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
122 ASSERT_TRUE(compute_pipeline);
123
124 auto cmd_buffer = context->CreateCommandBuffer();
125 auto pass = cmd_buffer->CreateComputePass();
126 ASSERT_TRUE(pass && pass->IsValid());
127
128 static constexpr size_t kCount = 5;
129
130 pass->SetPipeline(compute_pipeline);
131
132 CS::InputData<kCount> input_data;
133 input_data.count = kCount;
134 for (size_t i = 0; i < kCount; i++) {
135 input_data.data[i] = 1 + i;
136 }
137
138 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
139 context, "Output Buffer");
140
141 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
142 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
143
144 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
145 ASSERT_TRUE(pass->EncodeCommands());
146
147 fml::AutoResetWaitableEvent latch;
148 ASSERT_TRUE(
149 context->GetCommandQueue()
150 ->Submit({cmd_buffer},
151 [&latch, output_buffer](CommandBuffer::Status status) {
152 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
153
154 auto view = DeviceBuffer::AsBufferView(output_buffer);
155 EXPECT_EQ(view.range.length,
156 sizeof(CS::OutputData<kCount>));
157
158 CS::OutputData<kCount>* output =
159 reinterpret_cast<CS::OutputData<kCount>*>(
160 output_buffer->OnGetContents());
161 EXPECT_TRUE(output);
162
163 constexpr uint32_t expected[kCount] = {1, 3, 6, 10, 15};
164 for (size_t i = 0; i < kCount; i++) {
165 auto computed_sum = output->data[i];
166 EXPECT_EQ(computed_sum, expected[i]);
167 }
168 latch.Signal();
169 })
170 .ok());
171
172 latch.Wait();
173 }

References impeller::DeviceBuffer::AsBufferView(), and impeller::HostBuffer::Create().

## ◆ TEST_P() [221/419]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanComputePrefixSumLargeInteractive |
| ) |  |

Definition at line 228 of file compute_unittests.cc.

228 {
229 using CS = PrefixSumTestComputeShader;
230
231 auto context = GetContext();
232 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
233
234 ASSERT_TRUE(context);
235 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
236
237 auto callback = [&](RenderPass& render_pass) -> bool {
238 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
239 auto pipeline_desc =
240 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
241 auto compute_pipeline =
242 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
243
244 auto cmd_buffer = context->CreateCommandBuffer();
245 auto pass = cmd_buffer->CreateComputePass();
246
247 static constexpr size_t kCount = 1023;
248
249 pass->SetPipeline(compute_pipeline);
250
251 CS::InputData<kCount> input_data;
252 input_data.count = kCount;
253 for (size_t i = 0; i < kCount; i++) {
254 input_data.data[i] = 1 + i;
255 }
256
257 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
258 context, "Output Buffer");
259
260 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
261 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
262
263 pass->Compute(ISize(kCount, 1));
264 pass->EncodeCommands();
265 host_buffer->Reset();
266 return context->GetCommandQueue()->Submit({cmd_buffer}).ok();
267 };
268 ASSERT_TRUE(OpenPlaygroundHere(callback));
269 }

## ◆ TEST_P() [222/419]

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 ASSERT_TRUE(context);
35 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
36
37 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
38 auto pipeline_desc =
39 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
40 ASSERT_TRUE(pipeline_desc.has_value());
41 auto compute_pipeline =
42 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
43 ASSERT_TRUE(compute_pipeline);
44
45 auto cmd_buffer = context->CreateCommandBuffer();
46 auto pass = cmd_buffer->CreateComputePass();
47 ASSERT_TRUE(pass && pass->IsValid());
48
49 static constexpr size_t kCount = 5;
50
51 pass->SetPipeline(compute_pipeline);
52
53 CS::Info info{.count = kCount};
54 CS::Input0<kCount> input_0;
55 CS::Input1<kCount> input_1;
56 for (size_t i = 0; i < kCount; i++) {
57 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
58 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
59 }
60
61 input_0.fixed_array[1] = IPoint32(2, 2);
62 input_1.fixed_array[0] = UintPoint32(3, 3);
63 input_0.some_int = 5;
64 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
65
66 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
67 context, "Output Buffer");
68
69 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
70 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
71 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
72 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
73
74 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
75 ASSERT_TRUE(pass->EncodeCommands());
76
77 fml::AutoResetWaitableEvent latch;
78 ASSERT_TRUE(
79 context->GetCommandQueue()
80 ->Submit(
81 {cmd_buffer},
82 [&latch, output_buffer, &input_0,
83 &input_1](CommandBuffer::Status status) {
84 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
85
86 auto view = DeviceBuffer::AsBufferView(output_buffer);
87 EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
88
89 CS::Output<kCount>* output =
90 reinterpret_cast<CS::Output<kCount>*>(
91 output_buffer->OnGetContents());
92 EXPECT_TRUE(output);
93 for (size_t i = 0; i < kCount; i++) {
94 Vector4 vector = output->elements[i];
95 Vector4 computed = input_0.elements[i] * input_1.elements[i];
96 EXPECT_EQ(vector,
97 Vector4(computed.x + 2 + input_1.some_struct.i,
98 computed.y + 3 + input_1.some_struct.vf.x,
99 computed.z + 5 + input_1.some_struct.vf.y,
100 computed.w));
101 }
102 latch.Signal();
103 })
104 .ok());
105
106 latch.Wait();
107 }

References impeller::DeviceBuffer::AsBufferView(), and impeller::HostBuffer::Create().

## ◆ TEST_P() [223/419]

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

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | MultiStageInputAndOutput |
| ) |  |

Definition at line 271 of file compute_unittests.cc.

271 {
272 using CS1 = Stage1ComputeShader;
273 using Stage1PipelineBuilder = ComputePipelineBuilder<CS1>;
274 using CS2 = Stage2ComputeShader;
275 using Stage2PipelineBuilder = ComputePipelineBuilder<CS2>;
276
277 auto context = GetContext();
278 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
279 ASSERT_TRUE(context);
280 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
281
282 auto pipeline_desc_1 =
283 Stage1PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
284 ASSERT_TRUE(pipeline_desc_1.has_value());
285 auto compute_pipeline_1 =
286 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_1).Get();
287 ASSERT_TRUE(compute_pipeline_1);
288
289 auto pipeline_desc_2 =
290 Stage2PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
291 ASSERT_TRUE(pipeline_desc_2.has_value());
292 auto compute_pipeline_2 =
293 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_2).Get();
294 ASSERT_TRUE(compute_pipeline_2);
295
296 auto cmd_buffer = context->CreateCommandBuffer();
297 auto pass = cmd_buffer->CreateComputePass();
298 ASSERT_TRUE(pass && pass->IsValid());
299
300 static constexpr size_t kCount1 = 5;
301 static constexpr size_t kCount2 = kCount1 * 2;
302
303 CS1::Input<kCount1> input_1;
304 input_1.count = kCount1;
305 for (size_t i = 0; i < kCount1; i++) {
306 input_1.elements[i] = i;
307 }
308
309 CS2::Input<kCount2> input_2;
310 input_2.count = kCount2;
311 for (size_t i = 0; i < kCount2; i++) {
312 input_2.elements[i] = i;
313 }
314
315 auto output_buffer_1 = CreateHostVisibleDeviceBuffer<CS1::Output<kCount2>>(
316 context, "Output Buffer Stage 1");
317 auto output_buffer_2 = CreateHostVisibleDeviceBuffer<CS2::Output<kCount2>>(
318 context, "Output Buffer Stage 2");
319
320 {
321 pass->SetPipeline(compute_pipeline_1);
322
323 CS1::BindInput(*pass, host_buffer->EmplaceStorageBuffer(input_1));
324 CS1::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
325
326 ASSERT_TRUE(pass->Compute(ISize(512, 1)).ok());
327 pass->AddBufferMemoryBarrier();
328 }
329
330 {
331 pass->SetPipeline(compute_pipeline_2);
332
333 CS1::BindInput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
334 CS2::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_2));
335 ASSERT_TRUE(pass->Compute(ISize(512, 1)).ok());
336 }
337
338 ASSERT_TRUE(pass->EncodeCommands());
339
340 fml::AutoResetWaitableEvent latch;
341 ASSERT_TRUE(
342 context->GetCommandQueue()
343 ->Submit({cmd_buffer},
344 [&latch, &output_buffer_1,
345 &output_buffer_2](CommandBuffer::Status status) {
346 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
347
348 CS1::Output<kCount2>* output_1 =
349 reinterpret_cast<CS1::Output<kCount2>*>(
350 output_buffer_1->OnGetContents());
351 EXPECT_TRUE(output_1);
352 EXPECT_EQ(output_1->count, 10u);
353 EXPECT_THAT(
354 output_1->elements,
355 ::testing::ElementsAre(0, 0, 2, 3, 4, 6, 6, 9, 8, 12));
356
357 CS2::Output<kCount2>* output_2 =
358 reinterpret_cast<CS2::Output<kCount2>*>(
359 output_buffer_2->OnGetContents());
360 EXPECT_TRUE(output_2);
361 EXPECT_EQ(output_2->count, 10u);
362 EXPECT_THAT(output_2->elements,
363 ::testing::ElementsAre(0, 0, 4, 6, 8, 12, 12,
364 18, 16, 24));
365
366 latch.Signal();
367 })
368 .ok());
369
370 latch.Wait();
371 }

References impeller::kCount1.

## ◆ TEST_P() [225/419]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | ReturnsEarlyWhenAnyGridDimensionIsZero |
| ) |  |

Definition at line 452 of file compute_unittests.cc.

452 {
453 using CS = SampleComputeShader;
454 auto context = GetContext();
455 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
456 ASSERT_TRUE(context);
457 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
458
459 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
460 auto pipeline_desc =
461 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
462 ASSERT_TRUE(pipeline_desc.has_value());
463 auto compute_pipeline =
464 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
465 ASSERT_TRUE(compute_pipeline);
466
467 auto cmd_buffer = context->CreateCommandBuffer();
468 auto pass = cmd_buffer->CreateComputePass();
469 ASSERT_TRUE(pass && pass->IsValid());
470
471 static constexpr size_t kCount = 5;
472
473 pass->SetPipeline(compute_pipeline);
474
475 CS::Info info{.count = kCount};
476 CS::Input0<kCount> input_0;
477 CS::Input1<kCount> input_1;
478 for (size_t i = 0; i < kCount; i++) {
479 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
480 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
481 }
482
483 input_0.fixed_array[1] = IPoint32(2, 2);
484 input_1.fixed_array[0] = UintPoint32(3, 3);
485 input_0.some_int = 5;
486 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
487
488 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
489 context, "Output Buffer");
490
491 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
492 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
493 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
494 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
495
496 // Intentionally making the grid size zero in one dimension. No GPU will
497 // tolerate this.
498 EXPECT_FALSE(pass->Compute(ISize(0, 1)).ok());
499 pass->EncodeCommands();
500 }

## ◆ TEST_P() [226/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanBlendDstOverAndDstCorrectly |
| ) |  |

Definition at line 1266 of file dl_unittests.cc.

1266 {
1267 flutter::DisplayListBuilder builder;
1268
1269 {
1270 builder.SaveLayer(nullptr, nullptr);
1271 builder.Translate(100, 100);
1272 flutter::DlPaint paint;
1273 paint.setColor(flutter::DlColor::kRed());
1274 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1275 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1276 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
1277 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1278 builder.Restore();
1279 }
1280 {
1281 builder.SaveLayer(nullptr, nullptr);
1282 builder.Translate(300, 100);
1283 flutter::DlPaint paint;
1284 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1285 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1286 paint.setColor(flutter::DlColor::kRed());
1287 paint.setBlendMode(flutter::DlBlendMode::kDstOver);
1288 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1289 builder.Restore();
1290 }
1291 {
1292 builder.SaveLayer(nullptr, nullptr);
1293 builder.Translate(100, 300);
1294 flutter::DlPaint paint;
1295 paint.setColor(flutter::DlColor::kRed());
1296 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1297 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1298 paint.setBlendMode(flutter::DlBlendMode::kSrc);
1299 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1300 builder.Restore();
1301 }
1302 {
1303 builder.SaveLayer(nullptr, nullptr);
1304 builder.Translate(300, 300);
1305 flutter::DlPaint paint;
1306 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1307 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1308 paint.setColor(flutter::DlColor::kRed());
1309 paint.setBlendMode(flutter::DlBlendMode::kDst);
1310 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1311 builder.Restore();
1312 }
1313
1314 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1315 }

## ◆ TEST_P() [227/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanClampTheResultingColorOfColorMatrixFilter |
| ) |  |

Definition at line 616 of file dl_unittests.cc.

616 {
617 auto texture = CreateTextureForFixture("boston.jpg");
618 const float inner_color_matrix[20] = {
619 1, 0, 0, 0, 0, //
620 0, 1, 0, 0, 0, //
621 0, 0, 1, 0, 0, //
622 0, 0, 0, 2, 0, //
623 };
624 const float outer_color_matrix[20] = {
625 1, 0, 0, 0, 0, //
626 0, 1, 0, 0, 0, //
627 0, 0, 1, 0, 0, //
628 0, 0, 0, 0.5, 0, //
629 };
630 auto inner_color_filter =
631 std::make_shared<flutter::DlMatrixColorFilter>(inner_color_matrix);
632 auto outer_color_filter =
633 std::make_shared<flutter::DlMatrixColorFilter>(outer_color_matrix);
634 auto inner =
635 std::make_shared<flutter::DlColorFilterImageFilter>(inner_color_filter);
636 auto outer =
637 std::make_shared<flutter::DlColorFilterImageFilter>(outer_color_filter);
638 auto compose = std::make_shared<flutter::DlComposeImageFilter>(outer, inner);
639
640 flutter::DisplayListBuilder builder;
641 flutter::DlPaint paint;
642 paint.setImageFilter(compose.get());
643 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
644 flutter::DlImageSampling::kNearestNeighbor, &paint);
645 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
646 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [228/419]

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

Definition at line 977 of file dl_unittests.cc.

977 {
978 constexpr Scalar hexagon_radius = 125;
979 auto hex_start = Point(200.0, -hexagon_radius + 200.0);
980 auto center_to_flat = 1.73 / 2 * hexagon_radius;
981
982 // clang-format off
983 std::vector<SkPoint> vertices = {
984 SkPoint::Make(hex_start.x, hex_start.y),
985 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 0.5 * hexagon_radius),
986 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
987 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
988 SkPoint::Make(hex_start.x, hex_start.y + 2 * hexagon_radius),
989 SkPoint::Make(hex_start.x, hex_start.y + 2 * hexagon_radius),
990 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
991 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
992 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 0.5 * hexagon_radius)
993 };
994 // clang-format on
995 auto paint = flutter::DlPaint(flutter::DlColor::kDarkGrey());
996 auto dl_vertices = flutter::DlVertices::Make(
997 flutter::DlVertexMode::kTriangleFan, vertices.size(), vertices.data(),
998 nullptr, nullptr);
999 flutter::DisplayListBuilder builder;
1000 builder.DrawVertices(dl_vertices, flutter::DlBlendMode::kSrcOver, paint);
1001 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1002 }

## ◆ TEST_P() [229/419]

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

Definition at line 406 of file dl_unittests.cc.

406 {
407 flutter::DisplayListBuilder builder;
408 flutter::DlPaint paint;
409
410 paint.setColor(flutter::DlColor::kRed());
411 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
412 paint.setStrokeWidth(10);
413
414 builder.Translate(300, 300);
415
416 // Move to (50, 50) and draw lines from:
417 // 1. (50, height)
418 // 2. (width, height)
419 // 3. (width, 50)
420 SkPath path;
421 path.moveTo(50, 50);
422 path.lineTo(50, 100);
423 path.lineTo(100, 100);
424 path.lineTo(100, 50);
425 builder.DrawPath(path, paint);
426
427 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
428 }

## ◆ TEST_P() [230/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawArc |
| ) |  |

Definition at line 152 of file dl_unittests.cc.

152 {
153 auto callback = [&]() {
154 static float start_angle = 45;
155 static float sweep_angle = 270;
156 static float stroke_width = 10;
157 static bool use_center = true;
158
159 static int selected_cap = 0;
160 const char* cap_names[] = {"Butt", "Round", "Square"};
161 flutter::DlStrokeCap cap;
162
163 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
164 ImGui::SliderFloat("Start angle", &start_angle, -360, 360);
165 ImGui::SliderFloat("Sweep angle", &sweep_angle, -360, 360);
166 ImGui::SliderFloat("Stroke width", &stroke_width, 0, 300);
167 ImGui::Combo("Cap", &selected_cap, cap_names,
168 sizeof(cap_names) / sizeof(char*));
169 ImGui::Checkbox("Use center", &use_center);
170 ImGui::End();
171
172 switch (selected_cap) {
173 case 0:
174 cap = flutter::DlStrokeCap::kButt;
175 break;
176 case 1:
177 cap = flutter::DlStrokeCap::kRound;
178 break;
179 case 2:
180 cap = flutter::DlStrokeCap::kSquare;
181 break;
182 default:
183 cap = flutter::DlStrokeCap::kButt;
184 break;
185 }
186
187 static PlaygroundPoint point_a(Point(200, 200), 20, Color::White());
188 static PlaygroundPoint point_b(Point(400, 400), 20, Color::White());
189 auto [p1, p2] = DrawPlaygroundLine(point_a, point_b);
190
191 flutter::DisplayListBuilder builder;
192 flutter::DlPaint paint;
193
194 Vector2 scale = GetContentScale();
195 builder.Scale(scale.x, scale.y);
196 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
197 paint.setStrokeCap(cap);
198 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
199 paint.setStrokeMiter(10);
200 auto rect = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
201 paint.setColor(flutter::DlColor::kGreen());
202 paint.setStrokeWidth(2);
203 builder.DrawRect(rect, paint);
204 paint.setColor(flutter::DlColor::kRed());
205 paint.setStrokeWidth(stroke_width);
206 builder.DrawArc(rect, start_angle, sweep_angle, use_center, paint);
207
208 return builder.Build();
209 };
210 ASSERT_TRUE(OpenPlaygroundHere(callback));
211 }

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

## ◆ TEST_P() [231/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawBackdropFilter |
| ) |  |

Definition at line 648 of file dl_unittests.cc.

648 {
649 auto texture = CreateTextureForFixture("embarcadero.jpg");
650
651 auto callback = [&]() {
652 static float sigma[] = {10, 10};
653 static float ctm_scale = 1;
654 static bool use_bounds = true;
655 static bool draw_circle = true;
656 static bool add_clip = true;
657
658 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
659 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
660 ImGui::SliderFloat("Scale", &ctm_scale, 0, 10);
661 ImGui::NewLine();
662 ImGui::TextWrapped(
663 "If everything is working correctly, none of the options below should "
664 "impact the filter's appearance.");
665 ImGui::Checkbox("Use SaveLayer bounds", &use_bounds);
666 ImGui::Checkbox("Draw child element", &draw_circle);
667 ImGui::Checkbox("Add pre-clip", &add_clip);
668 ImGui::End();
669
670 flutter::DisplayListBuilder builder;
671
672 Vector2 scale = ctm_scale * GetContentScale();
673 builder.Scale(scale.x, scale.y);
674
675 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
676 flutter::DlTileMode::kClamp);
677
678 std::optional<SkRect> bounds;
679 if (use_bounds) {
680 static PlaygroundPoint point_a(Point(350, 150), 20, Color::White());
681 static PlaygroundPoint point_b(Point(800, 600), 20, Color::White());
682 auto [p1, p2] = DrawPlaygroundLine(point_a, point_b);
683 bounds = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
684 }
685
686 // Insert a clip to test that the backdrop filter handles stencil depths > 0
687 // correctly.
688 if (add_clip) {
689 builder.ClipRect(SkRect::MakeLTRB(0, 0, 99999, 99999),
690 flutter::DlCanvas::ClipOp::kIntersect, true);
691 }
692
693 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
694 flutter::DlImageSampling::kNearestNeighbor, nullptr);
695 builder.SaveLayer(bounds.has_value() ? &bounds.value() : nullptr, nullptr,
696 &filter);
697
698 if (draw_circle) {
699 static PlaygroundPoint center_point(Point(500, 400), 20, Color::Red());
700 auto circle_center = DrawPlaygroundPoint(center_point);
701
702 flutter::DlPaint paint;
703 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
704 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
705 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
706 paint.setStrokeWidth(10);
707 paint.setColor(flutter::DlColor::kRed().withAlpha(100));
708 builder.DrawCircle({circle_center.x, circle_center.y}, 100, paint);
709 }
710
711 return builder.Build();
712 };
713
714 ASSERT_TRUE(OpenPlaygroundHere(callback));
715 }

References impeller::DrawPlaygroundLine(), impeller::DrawPlaygroundPoint(), impeller::DlImageImpeller::Make(), impeller::Color::Red(), scale, and impeller::Color::White().

## ◆ TEST_P() [232/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCapsAndJoins |
| ) |  |

Definition at line 106 of file dl_unittests.cc.

106 {
107 flutter::DisplayListBuilder builder;
108 flutter::DlPaint paint;
109
110 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
111 paint.setStrokeWidth(30);
112 paint.setColor(flutter::DlColor::kRed());
113
114 auto path =
115 SkPathBuilder{}.moveTo(-50, 0).lineTo(0, -50).lineTo(50, 0).snapshot();
116
117 builder.Translate(100, 100);
118 {
119 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
120 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
121 paint.setStrokeMiter(4);
122 builder.DrawPath(path, paint);
123 }
124
125 {
126 builder.Save();
127 builder.Translate(0, 100);
128 // The joint in the path is 45 degrees. A miter length of 1 convert to a
129 // bevel in this case.
130 paint.setStrokeMiter(1);
131 builder.DrawPath(path, paint);
132 builder.Restore();
133 }
134
135 builder.Translate(150, 0);
136 {
137 paint.setStrokeCap(flutter::DlStrokeCap::kSquare);
138 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
139 builder.DrawPath(path, paint);
140 }
141
142 builder.Translate(150, 0);
143 {
144 paint.setStrokeCap(flutter::DlStrokeCap::kRound);
145 paint.setStrokeJoin(flutter::DlStrokeJoin::kRound);
146 builder.DrawPath(path, paint);
147 }
148
149 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
150 }

## ◆ TEST_P() [233/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCorrectlyWithColorFilterAndImageFilter |
| ) |  |

Definition at line 1317 of file dl_unittests.cc.

1317 {
1318 flutter::DisplayListBuilder builder;
1319 const float green_color_matrix[20] = {
1320 0, 0, 0, 0, 0, //
1321 0, 0, 0, 0, 1, //
1322 0, 0, 0, 0, 0, //
1323 0, 0, 0, 1, 0, //
1324 };
1325 const float blue_color_matrix[20] = {
1326 0, 0, 0, 0, 0, //
1327 0, 0, 0, 0, 0, //
1328 0, 0, 0, 0, 1, //
1329 0, 0, 0, 1, 0, //
1330 };
1331 auto green_color_filter =
1332 std::make_shared<flutter::DlMatrixColorFilter>(green_color_matrix);
1333 auto blue_color_filter =
1334 std::make_shared<flutter::DlMatrixColorFilter>(blue_color_matrix);
1335 auto blue_image_filter =
1336 std::make_shared<flutter::DlColorFilterImageFilter>(blue_color_filter);
1337
1338 flutter::DlPaint paint;
1339 paint.setColor(flutter::DlColor::kRed());
1340 paint.setColorFilter(green_color_filter);
1341 paint.setImageFilter(blue_image_filter);
1342 builder.DrawRect(SkRect::MakeLTRB(100, 100, 500, 500), paint);
1343 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1344 }

## ◆ TEST_P() [234/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawImage |
| ) |  |

Definition at line 98 of file dl_unittests.cc.

98 {
99 auto texture = CreateTextureForFixture("embarcadero.jpg");
100 flutter::DisplayListBuilder builder;
101 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
102 flutter::DlImageSampling::kNearestNeighbor, nullptr);
103 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
104 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [235/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImage |
| ) |  |

Definition at line 717 of file dl_unittests.cc.

717 {
718 // Image is drawn with corners to scale and center pieces stretched to fit.
719 auto texture = CreateTextureForFixture("embarcadero.jpg");
720 flutter::DisplayListBuilder builder;
721 auto size = texture->GetSize();
722 builder.DrawImageNine(
723 DlImageImpeller::Make(texture),
724 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
725 size.height * 3 / 4),
726 SkRect::MakeLTRB(0, 0, size.width * 2, size.height * 2),
727 flutter::DlFilterMode::kNearest, nullptr);
728 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
729 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [236/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterBiggerThanDest |
| ) |  |

Definition at line 763 of file dl_unittests.cc.

763 {
764 // Edge case, the width and height of the corners does not leave any
765 // room for the center slices. Only the corners are displayed.
766 auto texture = CreateTextureForFixture("embarcadero.jpg");
767 flutter::DisplayListBuilder builder;
768 auto size = texture->GetSize();
769 builder.DrawImageNine(
770 DlImageImpeller::Make(texture),
771 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
772 size.height * 3 / 4),
773 SkRect::MakeLTRB(0, 0, size.width / 2, size.height / 2),
774 flutter::DlFilterMode::kNearest, nullptr);
775 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
776 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [237/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterHeightBiggerThanDest |
| ) |  |

Definition at line 747 of file dl_unittests.cc.

747 {
748 // Edge case, the height of the corners does not leave any room for the
749 // center slice. The center (across the horizontal axis) is folded out of the
750 // resulting image.
751 auto texture = CreateTextureForFixture("embarcadero.jpg");
752 flutter::DisplayListBuilder builder;
753 auto size = texture->GetSize();
754 builder.DrawImageNine(
755 DlImageImpeller::Make(texture),
756 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
757 size.height * 3 / 4),
758 SkRect::MakeLTRB(0, 0, size.width, size.height / 2),
759 flutter::DlFilterMode::kNearest, nullptr);
760 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
761 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [238/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterWidthBiggerThanDest |
| ) |  |

Definition at line 731 of file dl_unittests.cc.

731 {
732 // Edge case, the width of the corners does not leave any room for the
733 // center slice. The center (across the vertical axis) is folded out of the
734 // resulting image.
735 auto texture = CreateTextureForFixture("embarcadero.jpg");
736 flutter::DisplayListBuilder builder;
737 auto size = texture->GetSize();
738 builder.DrawImageNine(
739 DlImageImpeller::Make(texture),
740 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
741 size.height * 3 / 4),
742 SkRect::MakeLTRB(0, 0, size.width / 2, size.height),
743 flutter::DlFilterMode::kNearest, nullptr);
744 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
745 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [239/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCornersScaledDown |
| ) |  |

Definition at line 778 of file dl_unittests.cc.

778 {
779 // Edge case, there is not enough room for the corners to be drawn
780 // without scaling them down.
781 auto texture = CreateTextureForFixture("embarcadero.jpg");
782 flutter::DisplayListBuilder builder;
783 auto size = texture->GetSize();
784 builder.DrawImageNine(
785 DlImageImpeller::Make(texture),
786 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
787 size.height * 3 / 4),
788 SkRect::MakeLTRB(0, 0, size.width / 4, size.height / 4),
789 flutter::DlFilterMode::kNearest, nullptr);
790 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
791 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [240/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPaintWithColorSource |
| ) |  |

Definition at line 1214 of file dl_unittests.cc.

1214 {
1215 const flutter::DlColor colors[2] = {
1216 flutter::DlColor(0xFFF44336),
1217 flutter::DlColor(0xFF2196F3),
1218 };
1219 const float stops[2] = {0.0, 1.0};
1220 flutter::DlPaint paint;
1221 flutter::DisplayListBuilder builder;
1222 auto clip_bounds = SkRect::MakeWH(300.0, 300.0);
1223 builder.Save();
1224 builder.Translate(100, 100);
1225 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1226 auto linear =
1227 flutter::DlColorSource::MakeLinear({0.0, 0.0}, {100.0, 100.0}, 2, colors,
1228 stops, flutter::DlTileMode::kRepeat);
1229 paint.setColorSource(linear);
1230 builder.DrawPaint(paint);
1231 builder.Restore();
1232
1233 builder.Save();
1234 builder.Translate(500, 100);
1235 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1236 auto radial = flutter::DlColorSource::MakeRadial(
1237 {100.0, 100.0}, 100.0, 2, colors, stops, flutter::DlTileMode::kRepeat);
1238 paint.setColorSource(radial);
1239 builder.DrawPaint(paint);
1240 builder.Restore();
1241
1242 builder.Save();
1243 builder.Translate(100, 500);
1244 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1245 auto sweep =
1246 flutter::DlColorSource::MakeSweep({100.0, 100.0}, 180.0, 270.0, 2, colors,
1247 stops, flutter::DlTileMode::kRepeat);
1248 paint.setColorSource(sweep);
1249 builder.DrawPaint(paint);
1250 builder.Restore();
1251
1252 builder.Save();
1253 builder.Translate(500, 500);
1254 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1255 auto texture = CreateTextureForFixture("table_mountain_nx.png");
1256 auto image = std::make_shared<flutter::DlImageColorSource>(
1257 DlImageImpeller::Make(texture), flutter::DlTileMode::kRepeat,
1258 flutter::DlTileMode::kRepeat);
1259 paint.setColorSource(image);
1260 builder.DrawPaint(paint);
1261 builder.Restore();
1262
1263 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1264 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [241/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPoints |
| ) |  |

Definition at line 805 of file dl_unittests.cc.

805 {
806 flutter::DisplayListBuilder builder;
807 SkPoint points[7] = {
808 {0, 0}, //
809 {100, 100}, //
810 {100, 0}, //
811 {0, 100}, //
812 {0, 0}, //
813 {48, 48}, //
814 {52, 52}, //
815 };
816 std::vector<flutter::DlStrokeCap> caps = {
817 flutter::DlStrokeCap::kButt,
818 flutter::DlStrokeCap::kRound,
819 flutter::DlStrokeCap::kSquare,
820 };
821 flutter::DlPaint paint =
822 flutter::DlPaint() //
823 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
824 .setStrokeWidth(20);
825 builder.Translate(50, 50);
826 for (auto cap : caps) {
827 paint.setStrokeCap(cap);
828 builder.Save();
829 builder.DrawPoints(flutter::DlCanvas::PointMode::kPoints, 7, points, paint);
830 builder.Translate(150, 0);
831 builder.DrawPoints(flutter::DlCanvas::PointMode::kLines, 5, points, paint);
832 builder.Translate(150, 0);
833 builder.DrawPoints(flutter::DlCanvas::PointMode::kPolygon, 5, points,
834 paint);
835 builder.Restore();
836 builder.Translate(0, 150);
837 }
838 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
839 }

## ◆ TEST_P() [242/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRect |
| ) |  |

Definition at line 49 of file dl_unittests.cc.

49 {
50 flutter::DisplayListBuilder builder;
51 builder.DrawRect(SkRect::MakeXYWH(10, 10, 100, 100),
52 flutter::DlPaint(flutter::DlColor::kBlue()));
53 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
54 }

## ◆ TEST_P() [243/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRectWithLinearToSrgbColorFilter |
| ) |  |

Definition at line 1198 of file dl_unittests.cc.

1198 {
1199 flutter::DlPaint paint;
1200 paint.setColor(flutter::DlColor(0xFF2196F3).withAlpha(128));
1201 flutter::DisplayListBuilder builder;
1202 paint.setColorFilter(
1203 flutter::DlLinearToSrgbGammaColorFilter::kInstance.get());
1204 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
1205 builder.Translate(0, 200);
1206
1207 paint.setColorFilter(
1208 flutter::DlSrgbToLinearGammaColorFilter::kInstance.get());
1209 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
1210
1211 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1212 }

## ◆ TEST_P() [244/419]

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 SkScalar half_spike_rotation = kPi / star_spikes;
873 constexpr SkScalar radius = 40;
874 constexpr SkScalar spike_size = 10;
875 constexpr SkScalar outer_radius = radius + spike_size;
876 constexpr SkScalar inner_radius = radius - spike_size;
877 std::array<SkPoint, star_spikes * 2> star;
878 for (size_t i = 0; i < star_spikes; i++) {
879 const SkScalar rotation = half_spike_rotation * i * 2;
880 star[i * 2] = SkPoint::Make(50 + std::sin(rotation) * outer_radius,
881 50 - std::cos(rotation) * outer_radius);
882 star[i * 2 + 1] = SkPoint::Make(
883 50 + std::sin(rotation + half_spike_rotation) * inner_radius,
884 50 - std::cos(rotation + half_spike_rotation) * inner_radius);
885 }
886
887 std::array<SkPath, 4> paths = {
888 SkPath{}.addRect(SkRect::MakeXYWH(0, 0, 200, 100)),
889 SkPath{}.addRRect(
890 SkRRect::MakeRectXY(SkRect::MakeXYWH(20, 0, 200, 100), 30, 30)),
891 SkPath{}.addCircle(100, 50, 50),
892 SkPath{}.addPoly(star.data(), star.size(), true),
893 };
894 paint.setColor(flutter::DlColor::kWhite());
895 builder.DrawPaint(paint);
896 paint.setColor(flutter::DlColor::kCyan());
897 builder.Translate(100, 50);
898 for (size_t x = 0; x < paths.size(); x++) {
899 builder.Save();
900 for (size_t y = 0; y < 6; y++) {
901 builder.DrawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false,
902 1);
903 builder.DrawPath(paths[x], paint);
904 builder.Translate(0, 150);
905 }
906 builder.Restore();
907 builder.Translate(250, 0);
908 }
909
910 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
911 }

References impeller::kPi.

## ◆ TEST_P() [245/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawStrokedText |
| ) |  |

Definition at line 466 of file dl_unittests.cc.

466 {
467 flutter::DisplayListBuilder builder;
468 flutter::DlPaint paint;
469
470 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
471 paint.setColor(flutter::DlColor::kRed());
472 builder.DrawTextBlob(
473 SkTextBlob::MakeFromString("stoked about stroked text", CreateTestFont()),
474 250, 250, paint);
475
476 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
477 }

## ◆ TEST_P() [246/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextBlob |
| ) |  |

Definition at line 56 of file dl_unittests.cc.

56 {
57 flutter::DisplayListBuilder builder;
58 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
59 100, 100, flutter::DlPaint(flutter::DlColor::kBlue()));
60 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
61 }

## ◆ TEST_P() [247/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextBlobWithGradient |
| ) |  |

Definition at line 63 of file dl_unittests.cc.

63 {
64 flutter::DisplayListBuilder builder;
65
66 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
67 flutter::DlColor::kRed()};
68 const float stops[2] = {0.0, 1.0};
69
70 auto linear = flutter::DlColorSource::MakeLinear({0.0, 0.0}, {300.0, 300.0},
71 2, colors.data(), stops,
72 flutter::DlTileMode::kClamp);
73 flutter::DlPaint paint;
74 paint.setColorSource(linear);
75
76 builder.DrawTextBlob(
77 SkTextBlob::MakeFromString("Hello World", CreateTestFont()), 100, 100,
78 paint);
79 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
80 }

## ◆ TEST_P() [248/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextWithSaveLayer |
| ) |  |

Definition at line 82 of file dl_unittests.cc.

82 {
83 flutter::DisplayListBuilder builder;
84 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
85 100, 100, flutter::DlPaint(flutter::DlColor::kRed()));
86
87 flutter::DlPaint save_paint;
88 float alpha = 0.5;
89 save_paint.setAlpha(static_cast<uint8_t>(255 * alpha));
90 builder.SaveLayer(nullptr, &save_paint);
91 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello with half alpha",
92 CreateTestFontOfSize(100)),
93 100, 300, flutter::DlPaint(flutter::DlColor::kRed()));
94 builder.Restore();
95 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
96 }

## ◆ TEST_P() [249/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithBlendColorFilter |
| ) |  |

Definition at line 518 of file dl_unittests.cc.

518 {
519 auto texture = CreateTextureForFixture("embarcadero.jpg");
520 flutter::DisplayListBuilder builder;
521 flutter::DlPaint paint;
522
523 // Pipeline blended image.
524 {
525 auto filter = flutter::DlBlendColorFilter(flutter::DlColor::kYellow(),
526 flutter::DlBlendMode::kModulate);
527 paint.setColorFilter(&filter);
528 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
529 flutter::DlImageSampling::kNearestNeighbor, &paint);
530 }
531
532 // Advanced blended image.
533 {
534 auto filter = flutter::DlBlendColorFilter(flutter::DlColor::kRed(),
535 flutter::DlBlendMode::kScreen);
536 paint.setColorFilter(&filter);
537 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(250, 250),
538 flutter::DlImageSampling::kNearestNeighbor, &paint);
539 }
540
541 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
542 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [250/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithColorFilterImageFilter |
| ) |  |

Definition at line 544 of file dl_unittests.cc.

544 {
545 const float invert_color_matrix[20] = {
546 -1, 0, 0, 0, 1, //
547 0, -1, 0, 0, 1, //
548 0, 0, -1, 0, 1, //
549 0, 0, 0, 1, 0, //
550 };
551 auto texture = CreateTextureForFixture("boston.jpg");
552 flutter::DisplayListBuilder builder;
553 flutter::DlPaint paint;
554
555 auto color_filter =
556 std::make_shared<flutter::DlMatrixColorFilter>(invert_color_matrix);
557 auto image_filter =
558 std::make_shared<flutter::DlColorFilterImageFilter>(color_filter);
559
560 paint.setImageFilter(image_filter.get());
561 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
562 flutter::DlImageSampling::kNearestNeighbor, &paint);
563
564 builder.Translate(0, 700);
565 paint.setColorFilter(color_filter.get());
566 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
567 flutter::DlImageSampling::kNearestNeighbor, &paint);
568 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
569 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [251/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithComposeImageFilter |
| ) |  |

Definition at line 596 of file dl_unittests.cc.

596 {
597 auto texture = CreateTextureForFixture("boston.jpg");
598 flutter::DisplayListBuilder builder;
599 flutter::DlPaint paint;
600
601 auto dilate = std::make_shared<flutter::DlDilateImageFilter>(10.0, 10.0);
602 auto erode = std::make_shared<flutter::DlErodeImageFilter>(10.0, 10.0);
603 auto open = std::make_shared<flutter::DlComposeImageFilter>(dilate, erode);
604 auto close = std::make_shared<flutter::DlComposeImageFilter>(erode, dilate);
605
606 paint.setImageFilter(open.get());
607 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
608 flutter::DlImageSampling::kNearestNeighbor, &paint);
609 builder.Translate(0, 700);
610 paint.setImageFilter(close.get());
611 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
612 flutter::DlImageSampling::kNearestNeighbor, &paint);
613 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
614 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [252/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithImageBlurFilter |
| ) |  |

Definition at line 571 of file dl_unittests.cc.

571 {
572 auto texture = CreateTextureForFixture("embarcadero.jpg");
573
574 auto callback = [&]() {
575 static float sigma[] = {10, 10};
576
577 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
578 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
579 ImGui::End();
580
581 flutter::DisplayListBuilder builder;
582 flutter::DlPaint paint;
583
584 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
585 flutter::DlTileMode::kClamp);
586 paint.setImageFilter(&filter);
587 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
588 flutter::DlImageSampling::kNearestNeighbor, &paint);
589
590 return builder.Build();
591 };
592
593 ASSERT_TRUE(OpenPlaygroundHere(callback));
594 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [253/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMaskBlur |
| ) |  |

Definition at line 430 of file dl_unittests.cc.

430 {
431 auto texture = CreateTextureForFixture("embarcadero.jpg");
432 flutter::DisplayListBuilder builder;
433 flutter::DlPaint paint;
434
435 // Mask blurred image.
436 {
437 auto filter =
438 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
439 paint.setMaskFilter(&filter);
440 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
441 flutter::DlImageSampling::kNearestNeighbor, &paint);
442 }
443
444 // Mask blurred filled path.
445 {
446 paint.setColor(flutter::DlColor::kYellow());
447 auto filter =
448 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kOuter, 10.0f);
449 paint.setMaskFilter(&filter);
450 builder.DrawArc(SkRect::MakeXYWH(410, 110, 100, 100), 45, 270, true, paint);
451 }
452
453 // Mask blurred text.
454 {
455 auto filter =
456 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kSolid, 10.0f);
457 paint.setMaskFilter(&filter);
458 builder.DrawTextBlob(
459 SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170,
460 paint);
461 }
462
463 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
464 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [254/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilter |
| ) |  |

Definition at line 1038 of file dl_unittests.cc.

1038 {
1039 auto boston = CreateTextureForFixture("boston.jpg");
1040
1041 auto callback = [&]() {
1042 static int selected_matrix_type = 0;
1043 const char* matrix_type_names[] = {"Matrix", "Local Matrix"};
1044
1045 static float ctm_translation[2] = {200, 200};
1046 static float ctm_scale[2] = {0.65, 0.65};
1047 static float ctm_skew[2] = {0, 0};
1048
1049 static bool enable = true;
1050 static float translation[2] = {100, 100};
1051 static float scale[2] = {0.8, 0.8};
1052 static float skew[2] = {0.2, 0.2};
1053
1054 static bool enable_savelayer = true;
1055
1056 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1057 {
1058 ImGui::Combo("Filter type", &selected_matrix_type, matrix_type_names,
1059 sizeof(matrix_type_names) / sizeof(char*));
1060
1061 ImGui::TextWrapped("Current Transform");
1062 ImGui::SliderFloat2("CTM Translation", ctm_translation, 0, 1000);
1063 ImGui::SliderFloat2("CTM Scale", ctm_scale, 0, 3);
1064 ImGui::SliderFloat2("CTM Skew", ctm_skew, -3, 3);
1065
1066 ImGui::TextWrapped(
1067 "MatrixFilter and LocalMatrixFilter modify the CTM in the same way. "
1068 "The only difference is that MatrixFilter doesn't affect the effect "
1069 "transform, whereas LocalMatrixFilter does.");
1070 // Note: See this behavior in:
1071 // https://fiddle.skia.org/c/6cbb551ab36d06f163db8693972be954
1072 ImGui::Checkbox("Enable", &enable);
1073 ImGui::SliderFloat2("Filter Translation", translation, 0, 1000);
1074 ImGui::SliderFloat2("Filter Scale", scale, 0, 3);
1075 ImGui::SliderFloat2("Filter Skew", skew, -3, 3);
1076
1077 ImGui::TextWrapped(
1078 "Rendering the filtered image within a layer can expose bounds "
1079 "issues. If the rendered image gets cut off when this setting is "
1080 "enabled, there's a coverage bug in the filter.");
1081 ImGui::Checkbox("Render in layer", &enable_savelayer);
1082 }
1083 ImGui::End();
1084
1085 flutter::DisplayListBuilder builder;
1086 flutter::DlPaint paint;
1087
1088 if (enable_savelayer) {
1089 builder.SaveLayer(nullptr, nullptr);
1090 }
1091 {
1092 auto content_scale = GetContentScale();
1093 builder.Scale(content_scale.x, content_scale.y);
1094
1095 // Set the current transform
1096 auto ctm_matrix =
1097 SkMatrix::MakeAll(ctm_scale[0], ctm_skew[0], ctm_translation[0], //
1098 ctm_skew[1], ctm_scale[1], ctm_translation[1], //
1099 0, 0, 1);
1100 builder.Transform(ctm_matrix);
1101
1102 // Set the matrix filter
1103 auto filter_matrix =
1104 SkMatrix::MakeAll(scale[0], skew[0], translation[0], //
1105 skew[1], scale[1], translation[1], //
1106 0, 0, 1);
1107
1108 if (enable) {
1109 switch (selected_matrix_type) {
1110 case 0: {
1111 auto filter = flutter::DlMatrixImageFilter(
1112 filter_matrix, flutter::DlImageSampling::kLinear);
1113 paint.setImageFilter(&filter);
1114 break;
1115 }
1116 case 1: {
1117 auto internal_filter =
1118 flutter::DlBlurImageFilter(10, 10, flutter::DlTileMode::kDecal)
1119 .shared();
1120 auto filter = flutter::DlLocalMatrixImageFilter(filter_matrix,
1121 internal_filter);
1122 paint.setImageFilter(&filter);
1123 break;
1124 }
1125 }
1126 }
1127
1128 builder.DrawImage(DlImageImpeller::Make(boston), {},
1129 flutter::DlImageSampling::kLinear, &paint);
1130 }
1131 if (enable_savelayer) {
1132 builder.Restore();
1133 }
1134
1135 return builder.Build();
1136 };
1137
1138 ASSERT_TRUE(OpenPlaygroundHere(callback));
1139 }

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

## ◆ TEST_P() [255/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilterWhenSavingLayer |
| ) |  |

Definition at line 1141 of file dl_unittests.cc.

1141 {
1142 auto callback = [&]() {
1143 static float translation[2] = {0, 0};
1144 static bool enable_save_layer = true;
1145
1146 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1147 ImGui::SliderFloat2("Translation", translation, -130, 130);
1148 ImGui::Checkbox("Enable save layer", &enable_save_layer);
1149 ImGui::End();
1150
1151 flutter::DisplayListBuilder builder;
1152 builder.Save();
1153 builder.Scale(2.0, 2.0);
1154 flutter::DlPaint paint;
1155 paint.setColor(flutter::DlColor::kYellow());
1156 builder.DrawRect(SkRect::MakeWH(300, 300), paint);
1157 paint.setStrokeWidth(1.0);
1158 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1159 paint.setColor(flutter::DlColor::kBlack().withAlpha(0x80));
1160 builder.DrawLine(SkPoint::Make(150, 0), SkPoint::Make(150, 300), paint);
1161 builder.DrawLine(SkPoint::Make(0, 150), SkPoint::Make(300, 150), paint);
1162
1163 flutter::DlPaint save_paint;
1164 SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100);
1165 SkMatrix translate_matrix =
1166 SkMatrix::Translate(translation[0], translation[1]);
1167 if (enable_save_layer) {
1168 auto filter = flutter::DlMatrixImageFilter(
1169 translate_matrix, flutter::DlImageSampling::kNearestNeighbor);
1170 save_paint.setImageFilter(filter.shared());
1171 builder.SaveLayer(&bounds, &save_paint);
1172 } else {
1173 builder.Save();
1174 builder.Transform(translate_matrix);
1175 }
1176
1177 SkMatrix filter_matrix = SkMatrix::I();
1178 filter_matrix.postTranslate(-150, -150);
1179 filter_matrix.postScale(0.2f, 0.2f);
1180 filter_matrix.postTranslate(150, 150);
1181 auto filter = flutter::DlMatrixImageFilter(
1182 filter_matrix, flutter::DlImageSampling::kNearestNeighbor);
1183
1184 save_paint.setImageFilter(filter.shared());
1185
1186 builder.SaveLayer(&bounds, &save_paint);
1187 flutter::DlPaint paint2;
1188 paint2.setColor(flutter::DlColor::kBlue());
1189 builder.DrawRect(bounds, paint2);
1190 builder.Restore();
1191 builder.Restore();
1192 return builder.Build();
1193 };
1194
1195 ASSERT_TRUE(OpenPlaygroundHere(callback));
1196 }

## ◆ TEST_P() [256/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithOddPathWinding |
| ) |  |

Definition at line 386 of file dl_unittests.cc.

386 {
387 flutter::DisplayListBuilder builder;
388 flutter::DlPaint paint;
389
390 paint.setColor(flutter::DlColor::kRed());
391 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
392
393 builder.Translate(300, 300);
394 SkPath path;
395 path.setFillType(SkPathFillType::kEvenOdd);
396 path.addCircle(0, 0, 100);
397 path.addCircle(0, 0, 50);
398 builder.DrawPath(path, paint);
399
400 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
401 }

## ◆ TEST_P() [257/419]

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 SkPath path = SkPath().addPoly({{150, 50}, {150, 50}}, false);
855 for (auto cap : caps) {
856 paint.setStrokeCap(cap);
857 builder.DrawLine({50, 50}, {50, 50}, paint);
858 builder.DrawPath(path, paint);
859 builder.Translate(0, 150);
860 }
861 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
862 }

## ◆ TEST_P() [258/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroWidthLine |
| ) |  |

Definition at line 1004 of file dl_unittests.cc.

1004 {
1005 flutter::DisplayListBuilder builder;
1006 std::vector<flutter::DlStrokeCap> caps = {
1007 flutter::DlStrokeCap::kButt,
1008 flutter::DlStrokeCap::kRound,
1009 flutter::DlStrokeCap::kSquare,
1010 };
1011 flutter::DlPaint paint = //
1012 flutter::DlPaint() //
1013 .setColor(flutter::DlColor::kWhite()) //
1014 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1015 .setStrokeWidth(0);
1016 flutter::DlPaint outline_paint = //
1017 flutter::DlPaint() //
1018 .setColor(flutter::DlColor::kYellow()) //
1019 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1020 .setStrokeCap(flutter::DlStrokeCap::kSquare) //
1021 .setStrokeWidth(1);
1022 SkPath path = SkPath().addPoly({{150, 50}, {160, 50}}, false);
1023 for (auto cap : caps) {
1024 paint.setStrokeCap(cap);
1025 builder.DrawLine({50, 50}, {60, 50}, paint);
1026 builder.DrawRect({45, 45, 65, 55}, outline_paint);
1027 builder.DrawLine({100, 50}, {100, 50}, paint);
1028 if (cap != flutter::DlStrokeCap::kButt) {
1029 builder.DrawRect({95, 45, 105, 55}, outline_paint);
1030 }
1031 builder.DrawPath(path, paint);
1032 builder.DrawRect(path.getBounds().makeOutset(5, 5), outline_paint);
1033 builder.Translate(0, 150);
1034 }
1035 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1036 }

## ◆ TEST_P() [259/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | ClipDrawRRectWithNonCircularRadii |
| ) |  |

Definition at line 1598 of file dl_unittests.cc.

1598 {
1599 flutter::DisplayListBuilder builder;
1600
1601 flutter::DlPaint fill_paint = //
1602 flutter::DlPaint() //
1603 .setColor(flutter::DlColor::kBlue()) //
1604 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1605 .setStrokeWidth(10);
1606 flutter::DlPaint stroke_paint = //
1607 flutter::DlPaint() //
1608 .setColor(flutter::DlColor::kGreen()) //
1609 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1610 .setStrokeWidth(10);
1611
1612 builder.DrawRRect(
1613 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1614 fill_paint);
1615 builder.DrawRRect(
1616 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1617 stroke_paint);
1618
1619 builder.DrawRRect(
1620 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1621 fill_paint);
1622 builder.DrawRRect(
1623 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1624 stroke_paint);
1625
1626 flutter::DlPaint reference_paint = //
1627 flutter::DlPaint() //
1628 .setColor(flutter::DlColor::kMidGrey()) //
1629 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1630 .setStrokeWidth(10);
1631
1632 builder.DrawRRect(
1633 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 500, 300, 300), 40, 40),
1634 reference_paint);
1635 builder.DrawRRect(
1636 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 100, 300, 300), 120, 120),
1637 reference_paint);
1638
1639 flutter::DlPaint clip_fill_paint = //
1640 flutter::DlPaint() //
1641 .setColor(flutter::DlColor::kCyan()) //
1642 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1643 .setStrokeWidth(10);
1644
1645 builder.Save();
1646 builder.ClipRRect(
1647 SkRRect::MakeRectXY(SkRect::MakeXYWH(900, 100, 300, 300), 120, 40));
1648 builder.DrawPaint(clip_fill_paint);
1649 builder.Restore();
1650
1651 builder.Save();
1652 builder.ClipRRect(
1653 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 900, 300, 300), 40, 120));
1654 builder.DrawPaint(clip_fill_paint);
1655 builder.Restore();
1656
1657 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1658 }

## ◆ TEST_P() [260/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DispatcherDoesNotCullPerspectiveTransformedChildDisplayLists |
| ) |  |

Definition at line 913 of file dl_unittests.cc.

914 {
915 // Regression test for https://github.com/flutter/flutter/issues/130613
916 flutter::DisplayListBuilder sub_builder(true);
917 sub_builder.DrawRect(SkRect::MakeXYWH(0, 0, 50, 50),
918 flutter::DlPaint(flutter::DlColor::kRed()));
919 auto display_list = sub_builder.Build();
920
921 DlDispatcher dispatcher(Rect::MakeLTRB(0, 0, 2400, 1800));
922 dispatcher.scale(2.0, 2.0);
923 dispatcher.translate(-93.0, 0.0);
924 // clang-format off
925 dispatcher.transformFullPerspective(
926 0.8, -0.2, -0.1, -0.0,
927 0.0, 1.0, 0.0, 0.0,
928 1.4, 1.3, 1.0, 0.0,
929 63.2, 65.3, 48.6, 1.1
930 );
931 // clang-format on
932 dispatcher.translate(35.0, 75.0);
933 dispatcher.drawDisplayList(display_list, 1.0f);
934 auto picture = dispatcher.EndRecordingAsPicture();
935
936 bool found = false;
937 picture.pass->IterateAllEntities([&found](Entity& entity) {
938 if (std::static_pointer_cast<SolidColorContents>(entity.GetContents())
939 ->GetColor() == Color::Red()) {
940 found = true;
941 return false;
942 }
943
944 return true;
945 });
946 EXPECT_TRUE(found);
947 }

References impeller::DlDispatcher::drawDisplayList(), impeller::DlDispatcher::EndRecordingAsPicture(), impeller::Entity::GetContents(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Picture::pass, impeller::Color::Red(), impeller::DlDispatcher::scale(), impeller::DlDispatcher::transformFullPerspective(), and impeller::DlDispatcher::translate().

## ◆ TEST_P() [261/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawPaintIgnoresMaskFilter |
| ) |  |

Definition at line 1837 of file dl_unittests.cc.

1837 {
1838 flutter::DisplayListBuilder builder;
1839 builder.DrawPaint(flutter::DlPaint().setColor(flutter::DlColor::kWhite()));
1840
1841 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
1842 builder.DrawCircle({300, 300}, 200,
1843 flutter::DlPaint().setMaskFilter(&filter));
1844
1845 std::vector<flutter::DlColor> colors = {flutter::DlColor::kGreen(),
1846 flutter::DlColor::kGreen()};
1847 const float stops[2] = {0.0, 1.0};
1848 auto linear = flutter::DlColorSource::MakeLinear(
1849 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1850 flutter::DlTileMode::kRepeat);
1851 flutter::DlPaint blend_paint =
1852 flutter::DlPaint() //
1853 .setColorSource(linear) //
1854 .setBlendMode(flutter::DlBlendMode::kScreen);
1855 builder.DrawPaint(blend_paint);
1856
1857 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1858 }

## ◆ TEST_P() [262/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawShapes |
| ) |  |

Definition at line 1560 of file dl_unittests.cc.

1560 {
1561 flutter::DisplayListBuilder builder;
1562 std::vector<flutter::DlStrokeJoin> joins = {
1563 flutter::DlStrokeJoin::kBevel,
1564 flutter::DlStrokeJoin::kRound,
1565 flutter::DlStrokeJoin::kMiter,
1566 };
1567 flutter::DlPaint paint = //
1568 flutter::DlPaint() //
1569 .setColor(flutter::DlColor::kWhite()) //
1570 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1571 .setStrokeWidth(10);
1572 flutter::DlPaint stroke_paint = //
1573 flutter::DlPaint() //
1574 .setColor(flutter::DlColor::kWhite()) //
1575 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1576 .setStrokeWidth(10);
1577 SkPath path = SkPath().addPoly({{150, 50}, {160, 50}}, false);
1578
1579 builder.Translate(300, 50);
1580 builder.Scale(0.8, 0.8);
1581 for (auto join : joins) {
1582 paint.setStrokeJoin(join);
1583 stroke_paint.setStrokeJoin(join);
1584 builder.DrawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
1585 builder.DrawRect(SkRect::MakeXYWH(0, 150, 100, 100), stroke_paint);
1586 builder.DrawRRect(
1587 SkRRect::MakeRectXY(SkRect::MakeXYWH(150, 0, 100, 100), 30, 30), paint);
1588 builder.DrawRRect(
1589 SkRRect::MakeRectXY(SkRect::MakeXYWH(150, 150, 100, 100), 30, 30),
1590 stroke_paint);
1591 builder.DrawCircle({350, 50}, 50, paint);
1592 builder.DrawCircle({350, 200}, 50, stroke_paint);
1593 builder.Translate(0, 300);
1594 }
1595 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1596 }

## ◆ TEST_P() [263/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesBlendModes |
| ) |  |

Definition at line 1660 of file dl_unittests.cc.

1660 {
1661 std::vector<const char*> blend_mode_names;
1662 std::vector<flutter::DlBlendMode> blend_mode_values;
1663 {
1664 const std::vector<std::tuple<const char*, flutter::DlBlendMode>> blends = {
1665 // Pipeline blends (Porter-Duff alpha compositing)
1666 {"Clear", flutter::DlBlendMode::kClear},
1667 {"Source", flutter::DlBlendMode::kSrc},
1668 {"Destination", flutter::DlBlendMode::kDst},
1669 {"SourceOver", flutter::DlBlendMode::kSrcOver},
1670 {"DestinationOver", flutter::DlBlendMode::kDstOver},
1671 {"SourceIn", flutter::DlBlendMode::kSrcIn},
1672 {"DestinationIn", flutter::DlBlendMode::kDstIn},
1673 {"SourceOut", flutter::DlBlendMode::kSrcOut},
1674 {"DestinationOut", flutter::DlBlendMode::kDstOut},
1675 {"SourceATop", flutter::DlBlendMode::kSrcATop},
1676 {"DestinationATop", flutter::DlBlendMode::kDstATop},
1677 {"Xor", flutter::DlBlendMode::kXor},
1678 {"Plus", flutter::DlBlendMode::kPlus},
1679 {"Modulate", flutter::DlBlendMode::kModulate},
1680 // Advanced blends (color component blends)
1681 {"Screen", flutter::DlBlendMode::kScreen},
1682 {"Overlay", flutter::DlBlendMode::kOverlay},
1683 {"Darken", flutter::DlBlendMode::kDarken},
1684 {"Lighten", flutter::DlBlendMode::kLighten},
1685 {"ColorDodge", flutter::DlBlendMode::kColorDodge},
1686 {"ColorBurn", flutter::DlBlendMode::kColorBurn},
1687 {"HardLight", flutter::DlBlendMode::kHardLight},
1688 {"SoftLight", flutter::DlBlendMode::kSoftLight},
1689 {"Difference", flutter::DlBlendMode::kDifference},
1690 {"Exclusion", flutter::DlBlendMode::kExclusion},
1691 {"Multiply", flutter::DlBlendMode::kMultiply},
1692 {"Hue", flutter::DlBlendMode::kHue},
1693 {"Saturation", flutter::DlBlendMode::kSaturation},
1694 {"Color", flutter::DlBlendMode::kColor},
1695 {"Luminosity", flutter::DlBlendMode::kLuminosity},
1696 };
1697 assert(blends.size() ==
1698 static_cast<size_t>(flutter::DlBlendMode::kLastMode) + 1);
1699 for (const auto& [name, mode] : blends) {
1700 blend_mode_names.push_back(name);
1701 blend_mode_values.push_back(mode);
1702 }
1703 }
1704
1705 auto callback = [&]() {
1706 static int current_blend_index = 3;
1707 static float dst_alpha = 1;
1708 static float src_alpha = 1;
1709 static float color0[4] = {1.0f, 0.0f, 0.0f, 1.0f};
1710 static float color1[4] = {0.0f, 1.0f, 0.0f, 1.0f};
1711 static float color2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
1712 static float src_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
1713
1714 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1715 {
1716 ImGui::ListBox("Blending mode", &current_blend_index,
1717 blend_mode_names.data(), blend_mode_names.size());
1718 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
1719 ImGui::ColorEdit4("Color A", color0);
1720 ImGui::ColorEdit4("Color B", color1);
1721 ImGui::ColorEdit4("Color C", color2);
1722 ImGui::ColorEdit4("Source Color", src_color);
1723 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
1724 }
1725 ImGui::End();
1726
1727 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1728 SkPoint::Make(200, 100),
1729 SkPoint::Make(300, 300)};
1730 std::vector<flutter::DlColor> colors = {
1731 toColor(color0).modulateOpacity(dst_alpha),
1732 toColor(color1).modulateOpacity(dst_alpha),
1733 toColor(color2).modulateOpacity(dst_alpha)};
1734
1735 auto vertices = flutter::DlVertices::Make(
1736 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1737 /*texture_coordinates=*/nullptr, colors.data());
1738
1739 flutter::DisplayListBuilder builder;
1740 flutter::DlPaint paint;
1741
1742 paint.setColor(toColor(src_color).modulateOpacity(src_alpha));
1743 builder.DrawVertices(vertices, blend_mode_values[current_blend_index],
1744 paint);
1745 return builder.Build();
1746 };
1747
1748 ASSERT_TRUE(OpenPlaygroundHere(callback));
1749 }

References impeller::kColor, and toColor().

## ◆ TEST_P() [264/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesImageSourceWithTextureCoordinates |
| ) |  |

Definition at line 1462 of file dl_unittests.cc.

1462 {
1463 auto texture = CreateTextureForFixture("embarcadero.jpg");
1464 auto dl_image = DlImageImpeller::Make(texture);
1465 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1466 SkPoint::Make(200, 100),
1467 SkPoint::Make(300, 300)};
1468 std::vector<SkPoint> texture_coordinates = {
1469 SkPoint::Make(0, 0), SkPoint::Make(100, 200), SkPoint::Make(200, 100)};
1470
1471 auto vertices = flutter::DlVertices::Make(
1472 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1473 texture_coordinates.data(), /*colors=*/nullptr);
1474
1475 flutter::DisplayListBuilder builder;
1476 flutter::DlPaint paint;
1477
1478 auto image_source = flutter::DlImageColorSource(
1479 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
1480
1481 paint.setColorSource(&image_source);
1482 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1483
1484 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1485 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [265/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesImageSourceWithTextureCoordinatesAndColorBlending |
| ) |  |

Definition at line 1487 of file dl_unittests.cc.

1488 {
1489 auto texture = CreateTextureForFixture("embarcadero.jpg");
1490 auto dl_image = DlImageImpeller::Make(texture);
1491 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1492 SkPoint::Make(200, 100),
1493 SkPoint::Make(300, 300)};
1494 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
1495 flutter::DlColor::kGreen(),
1496 flutter::DlColor::kWhite()};
1497 std::vector<SkPoint> texture_coordinates = {
1498 SkPoint::Make(0, 0), SkPoint::Make(100, 200), SkPoint::Make(200, 100)};
1499
1500 auto vertices = flutter::DlVertices::Make(
1501 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1502 texture_coordinates.data(), colors.data());
1503
1504 flutter::DisplayListBuilder builder;
1505 flutter::DlPaint paint;
1506
1507 auto image_source = flutter::DlImageColorSource(
1508 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
1509
1510 paint.setColorSource(&image_source);
1511 builder.DrawVertices(vertices, flutter::DlBlendMode::kModulate, paint);
1512
1513 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1514 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [266/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesLinearGradientWithoutIndices |
| ) |  |

Definition at line 1407 of file dl_unittests.cc.

1407 {
1408 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1409 SkPoint::Make(200, 100),
1410 SkPoint::Make(300, 300)};
1411
1412 auto vertices = flutter::DlVertices::Make(
1413 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1414 /*texture_coordinates=*/nullptr, /*colors=*/nullptr);
1415
1416 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
1417 flutter::DlColor::kRed()};
1418 const float stops[2] = {0.0, 1.0};
1419
1420 auto linear = flutter::DlColorSource::MakeLinear(
1421 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1422 flutter::DlTileMode::kRepeat);
1423
1424 flutter::DisplayListBuilder builder;
1425 flutter::DlPaint paint;
1426
1427 paint.setColorSource(linear);
1428 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1429
1430 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1431 }

## ◆ TEST_P() [267/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesLinearGradientWithTextureCoordinates |
| ) |  |

Definition at line 1433 of file dl_unittests.cc.

1433 {
1434 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1435 SkPoint::Make(200, 100),
1436 SkPoint::Make(300, 300)};
1437 std::vector<SkPoint> texture_coordinates = {SkPoint::Make(300, 100),
1438 SkPoint::Make(100, 200),
1439 SkPoint::Make(300, 300)};
1440
1441 auto vertices = flutter::DlVertices::Make(
1442 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1443 texture_coordinates.data(), /*colors=*/nullptr);
1444
1445 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
1446 flutter::DlColor::kRed()};
1447 const float stops[2] = {0.0, 1.0};
1448
1449 auto linear = flutter::DlColorSource::MakeLinear(
1450 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1451 flutter::DlTileMode::kRepeat);
1452
1453 flutter::DisplayListBuilder builder;
1454 flutter::DlPaint paint;
1455
1456 paint.setColorSource(linear);
1457 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1458
1459 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1460 }

## ◆ TEST_P() [268/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesPremultipliesColors |
| ) |  |

Definition at line 1536 of file dl_unittests.cc.

1536 {
1537 std::vector<SkPoint> positions = {
1538 SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
1539 SkPoint::Make(200, 500)};
1540 auto color = flutter::DlColor::kBlue().withAlpha(0x99);
1541 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
1542 std::vector<flutter::DlColor> colors = {color, color, color, color};
1543
1544 auto vertices = flutter::DlVertices::Make(
1545 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
1546 /*texture_coordinates=*/nullptr, colors.data(), indices.size(),
1547 indices.data());
1548
1549 flutter::DisplayListBuilder builder;
1550 flutter::DlPaint paint;
1551 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
1552 paint.setColor(flutter::DlColor::kRed());
1553
1554 builder.DrawRect(SkRect::MakeLTRB(0, 0, 400, 400), paint);
1555 builder.DrawVertices(vertices, flutter::DlBlendMode::kDst, paint);
1556
1557 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1558 }

## ◆ TEST_P() [269/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesSolidColorTrianglesWithIndices |
| ) |  |

Definition at line 1516 of file dl_unittests.cc.

1516 {
1517 std::vector<SkPoint> positions = {
1518 SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
1519 SkPoint::Make(200, 500)};
1520 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
1521
1522 auto vertices = flutter::DlVertices::Make(
1523 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
1524 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
1525 indices.data());
1526
1527 flutter::DisplayListBuilder builder;
1528 flutter::DlPaint paint;
1529
1530 paint.setColor(flutter::DlColor::kWhite());
1531 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1532
1533 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1534 }

## ◆ TEST_P() [270/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesSolidColorTrianglesWithoutIndices |
| ) |  |

Definition at line 1383 of file dl_unittests.cc.

1383 {
1384 // Use negative coordinates and then scale the transform by -1, -1 to make
1385 // sure coverage is taking the transform into account.
1386 std::vector<SkPoint> positions = {SkPoint::Make(-100, -300),
1387 SkPoint::Make(-200, -100),
1388 SkPoint::Make(-300, -300)};
1389 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
1390 flutter::DlColor::kGreen(),
1391 flutter::DlColor::kWhite()};
1392
1393 auto vertices = flutter::DlVertices::Make(
1394 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1395 /*texture_coordinates=*/nullptr, colors.data());
1396
1397 flutter::DisplayListBuilder builder;
1398 flutter::DlPaint paint;
1399
1400 paint.setColor(flutter::DlColor::kRed().modulateOpacity(0.5));
1401 builder.Scale(-1, -1);
1402 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1403
1404 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1405 }

## ◆ TEST_P() [271/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | IgnoreMaskFilterWhenSavingLayer |
| ) |  |

Definition at line 505 of file dl_unittests.cc.

505 {
506 auto texture = CreateTextureForFixture("embarcadero.jpg");
507 flutter::DisplayListBuilder builder;
508 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
509 flutter::DlPaint paint;
510 paint.setMaskFilter(&filter);
511 builder.SaveLayer(nullptr, &paint);
512 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
513 flutter::DlImageSampling::kNearestNeighbor);
514 builder.Restore();
515 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
516 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [272/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | MaskBlursApplyCorrectlyToColorSources |
| ) |  |

Definition at line 1346 of file dl_unittests.cc.

1346 {
1347 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
1348 flutter::DlBlurStyle::kNormal, 10);
1349
1350 flutter::DisplayListBuilder builder;
1351
1352 std::array<flutter::DlColor, 2> colors = {flutter::DlColor::kBlue(),
1353 flutter::DlColor::kGreen()};
1354 std::array<float, 2> stops = {0, 1};
1355 std::array<std::shared_ptr<flutter::DlColorSource>, 2> color_sources = {
1356 std::make_shared<flutter::DlColorColorSource>(flutter::DlColor::kWhite()),
1357 flutter::DlColorSource::MakeLinear(
1358 SkPoint::Make(0, 0), SkPoint::Make(100, 50), 2, colors.data(),
1359 stops.data(), flutter::DlTileMode::kClamp)};
1360
1361 int offset = 100;
1362 for (const auto& color_source : color_sources) {
1363 flutter::DlPaint paint;
1364 paint.setColorSource(color_source);
1365 paint.setMaskFilter(blur_filter);
1366
1367 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
1368 builder.DrawRRect(
1369 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, offset, 100, 50), 30, 30),
1370 paint);
1371 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1372 paint.setStrokeWidth(10);
1373 builder.DrawRRect(
1374 SkRRect::MakeRectXY(SkRect::MakeXYWH(300, offset, 100, 50), 30, 30),
1375 paint);
1376
1377 offset += 100;
1378 }
1379
1380 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1381 }

References offset.

## ◆ TEST_P() [273/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | NinePatchImagePrecision |
| ) |  |

Definition at line 793 of file dl_unittests.cc.

793 {
794 // Draw a nine patch image with colored corners and verify that the corner
795 // color does not leak outside the intended region.
796 auto texture = CreateTextureForFixture("nine_patch_corners.png");
797 flutter::DisplayListBuilder builder;
798 builder.DrawImageNine(DlImageImpeller::Make(texture),
799 SkIRect::MakeXYWH(10, 10, 1, 1),
800 SkRect::MakeXYWH(0, 0, 200, 100),
801 flutter::DlFilterMode::kNearest, nullptr);
802 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
803 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [274/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | StrokedPathsDrawCorrectly |
| ) |  |

Definition at line 213 of file dl_unittests.cc.

213 {
214 auto callback = [&]() {
215 flutter::DisplayListBuilder builder;
216 flutter::DlPaint paint;
217
218 paint.setColor(flutter::DlColor::kRed());
219 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
220
221 static float stroke_width = 10.0f;
222 static int selected_stroke_type = 0;
223 static int selected_join_type = 0;
224 const char* stroke_types[] = {"Butte", "Round", "Square"};
225 const char* join_type[] = {"kMiter", "Round", "kBevel"};
226
227 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
228 ImGui::Combo("Cap", &selected_stroke_type, stroke_types,
229 sizeof(stroke_types) / sizeof(char*));
230 ImGui::Combo("Join", &selected_join_type, join_type,
231 sizeof(join_type) / sizeof(char*));
232 ImGui::SliderFloat("Stroke Width", &stroke_width, 10.0f, 50.0f);
233 ImGui::End();
234
235 flutter::DlStrokeCap cap;
236 flutter::DlStrokeJoin join;
237 switch (selected_stroke_type) {
238 case 0:
239 cap = flutter::DlStrokeCap::kButt;
240 break;
241 case 1:
242 cap = flutter::DlStrokeCap::kRound;
243 break;
244 case 2:
245 cap = flutter::DlStrokeCap::kSquare;
246 break;
247 default:
248 cap = flutter::DlStrokeCap::kButt;
249 break;
250 }
251 switch (selected_join_type) {
252 case 0:
253 join = flutter::DlStrokeJoin::kMiter;
254 break;
255 case 1:
256 join = flutter::DlStrokeJoin::kRound;
257 break;
258 case 2:
259 join = flutter::DlStrokeJoin::kBevel;
260 break;
261 default:
262 join = flutter::DlStrokeJoin::kMiter;
263 break;
264 }
265 paint.setStrokeCap(cap);
266 paint.setStrokeJoin(join);
267 paint.setStrokeWidth(stroke_width);
268
269 // Make rendering better to watch.
270 builder.Scale(1.5f, 1.5f);
271
272 // Rectangle
273 builder.Translate(100, 100);
274 builder.DrawRect(SkRect::MakeSize({100, 100}), paint);
275
276 // Rounded rectangle
277 builder.Translate(150, 0);
278 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10),
279 paint);
280
281 // Double rounded rectangle
282 builder.Translate(150, 0);
283 builder.DrawDRRect(
284 SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10),
285 SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 30), 10, 10), paint);
286
287 // Contour with duplicate join points
288 {
289 builder.Translate(150, 0);
290 SkPath path;
291 path.moveTo(0, 0);
292 path.lineTo(0, 0);
293 path.lineTo({100, 0});
294 path.lineTo({100, 0});
295 path.lineTo({100, 100});
296 builder.DrawPath(path, 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 SkPath line_path;
307 line_path.moveTo(0, 0);
308 line_path.moveTo(0, 0);
309 line_path.lineTo({0, 0});
310 line_path.lineTo({0, 0});
311 line_path.lineTo({50, 50});
312 line_path.lineTo({50, 50});
313 line_path.lineTo({100, 0});
314 line_path.lineTo({100, 0});
315 builder.DrawPath(line_path, paint);
316
317 builder.Translate(0, 100);
318 builder.DrawPath(line_path, paint);
319
320 builder.Translate(0, 100);
321 SkPath line_path2;
322 line_path2.moveTo(0, 0);
323 line_path2.lineTo(0, 0);
324 line_path2.lineTo(0, 0);
325 builder.DrawPath(line_path2, paint);
326
327 builder.Restore();
328 }
329
330 // Cubic.
331 builder.Translate(150, 0);
332 {
333 builder.Save();
334
335 SkPath cubic_path;
336 cubic_path.moveTo({0, 0});
337 cubic_path.cubicTo(0, 0, 140.0, 100.0, 140, 20);
338 builder.DrawPath(cubic_path, paint);
339
340 builder.Translate(0, 100);
341 SkPath cubic_path2;
342 cubic_path2.moveTo({0, 0});
343 cubic_path2.cubicTo(0, 0, 0, 0, 150, 150);
344 builder.DrawPath(cubic_path2, paint);
345
346 builder.Translate(0, 100);
347 SkPath cubic_path3;
348 cubic_path3.moveTo({0, 0});
349 cubic_path3.cubicTo(0, 0, 0, 0, 0, 0);
350 builder.DrawPath(cubic_path3, paint);
351
352 builder.Restore();
353 }
354
355 // Quad.
356 builder.Translate(200, 0);
357 {
358 builder.Save();
359
360 SkPath quad_path;
361 quad_path.moveTo(0, 0);
362 quad_path.moveTo(0, 0);
363 quad_path.quadTo({100, 40}, {50, 80});
364 builder.DrawPath(quad_path, paint);
365
366 builder.Translate(0, 150);
367 SkPath quad_path2;
368 quad_path2.moveTo(0, 0);
369 quad_path2.moveTo(0, 0);
370 quad_path2.quadTo({0, 0}, {100, 100});
371 builder.DrawPath(quad_path2, paint);
372
373 builder.Translate(0, 100);
374 SkPath quad_path3;
375 quad_path3.moveTo(0, 0);
376 quad_path3.quadTo({0, 0}, {0, 0});
377 builder.DrawPath(quad_path3, paint);
378
379 builder.Restore();
380 }
381 return builder.Build();
382 };
383 ASSERT_TRUE(OpenPlaygroundHere(callback));
384 }

References stroke_width.

## ◆ TEST_P() [275/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | StrokedTextNotOffsetFromNormalText |
| ) |  |

Definition at line 480 of file dl_unittests.cc.

480 {
481 flutter::DisplayListBuilder builder;
482 flutter::DlPaint paint;
483 auto const& text_blob = SkTextBlob::MakeFromString("00000", CreateTestFont());
484
485 // https://api.flutter.dev/flutter/material/Colors/blue-constant.html.
486 auto const& mat_blue = flutter::DlColor(0xFF2196f3);
487
488 // Draw a blue filled rectangle so the text is easier to see.
489 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
490 paint.setColor(mat_blue);
491 builder.DrawRect(SkRect::MakeXYWH(0, 0, 500, 500), paint);
492
493 // Draw stacked text, with stroked text on top.
494 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
495 paint.setColor(flutter::DlColor::kWhite());
496 builder.DrawTextBlob(text_blob, 250, 250, paint);
497
498 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
499 paint.setColor(flutter::DlColor::kBlack());
500 builder.DrawTextBlob(text_blob, 250, 250, paint);
501
502 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
503 }

## ◆ TEST_P() [276/419]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | TransparentShadowProducesCorrectColor |
| ) |  |

Definition at line 949 of file dl_unittests.cc.

949 {
950 DlDispatcher dispatcher;
951 dispatcher.save();
952 dispatcher.scale(1.618, 1.618);
953 SkPath path = SkPath{}.addRect(SkRect::MakeXYWH(0, 0, 200, 100));
954 flutter::DlOpReceiver::CacheablePath cache(path);
955 dispatcher.drawShadow(cache, flutter::DlColor::kTransparent(), 15, false, 1);
956 dispatcher.restore();
957 auto picture = dispatcher.EndRecordingAsPicture();
958
959 std::shared_ptr<SolidRRectBlurContents> rrect_blur;
960 picture.pass->IterateAllEntities([&rrect_blur](Entity& entity) {
961 if (ScalarNearlyEqual(entity.GetTransform().GetScale().x, 1.618f)) {
962 rrect_blur = std::static_pointer_cast<SolidRRectBlurContents>(
963 entity.GetContents());
964 return false;
965 }
966 return true;
967 });
968
969 ASSERT_NE(rrect_blur, nullptr);
970 ASSERT_EQ(rrect_blur->GetColor().red, 0);
971 ASSERT_EQ(rrect_blur->GetColor().green, 0);
972 ASSERT_EQ(rrect_blur->GetColor().blue, 0);
973 ASSERT_EQ(rrect_blur->GetColor().alpha, 0);
974 }

References impeller::DlDispatcher::drawShadow(), impeller::DlDispatcher::EndRecordingAsPicture(), impeller::Matrix::GetScale(), impeller::Entity::GetTransform(), impeller::Picture::pass, impeller::DlDispatcher::restore(), impeller::DlDispatcher::save(), impeller::ScalarNearlyEqual(), impeller::DlDispatcher::scale(), and impeller::Vector3::x.

## ◆ TEST_P() [277/419]

impeller::testing::TEST_P | ( | DriverInfoVKTest | ,
|  | CanQueryDriverInfo |
| ) |  |

Definition at line 14 of file driver_info_vk_unittests.cc.

14 {
15 ASSERT_TRUE(GetContext());
16 const auto& driver_info =
17 SurfaceContextVK::Cast(*GetContext()).GetParent().GetDriverInfo();
18 ASSERT_NE(driver_info, nullptr);
19 // 1.1 is the base Impeller version. The driver can't be lower than that.
20 ASSERT_TRUE(driver_info->GetAPIVersion().IsAtLeast(Version{1, 1, 0}));
21 ASSERT_NE(driver_info->GetVendor(), VendorVK::kUnknown);
22 ASSERT_NE(driver_info->GetDeviceType(), DeviceTypeVK::kUnknown);
23 ASSERT_NE(driver_info->GetDriverName(), "");
24 }

References impeller::BackendCast< SurfaceContextVK, Context >::Cast(), impeller::ContextVK::GetDriverInfo(), impeller::SurfaceContextVK::GetParent(), and impeller::kUnknown.

## ◆ TEST_P() [278/419]

impeller::testing::TEST_P | ( | EntityPassTargetTest | ,
|  | SwapWithMSAAImplicitResolve |
| ) |  |

Definition at line 53 of file entity_pass_target_unittests.cc.

53 {
54 auto content_context = GetContentContext();
55 auto buffer = content_context->GetContext()->CreateCommandBuffer();
56 auto context = content_context->GetContext();
57 auto& allocator = *context->GetResourceAllocator();
58
59 // Emulate implicit MSAA resolve by making color resolve and msaa texture the
60 // same.
61 RenderTarget render_target;
62 {
63 PixelFormat pixel_format =
64 context->GetCapabilities()->GetDefaultColorFormat();
65
66 // Create MSAA color texture.
67
68 TextureDescriptor color0_tex_desc;
69 color0_tex_desc.storage_mode = StorageMode::kDevicePrivate;
70 color0_tex_desc.type = TextureType::kTexture2DMultisample;
71 color0_tex_desc.sample_count = SampleCount::kCount4;
72 color0_tex_desc.format = pixel_format;
73 color0_tex_desc.size = ISize{100, 100};
74 color0_tex_desc.usage = TextureUsage::kRenderTarget;
75
76 auto color0_msaa_tex = allocator.CreateTexture(color0_tex_desc);
77
78 // Color attachment.
79
80 ColorAttachment color0;
81 color0.load_action = LoadAction::kDontCare;
82 color0.store_action = StoreAction::kStoreAndMultisampleResolve;
83 color0.texture = color0_msaa_tex;
84 color0.resolve_texture = color0_msaa_tex;
85
86 render_target.SetColorAttachment(color0, 0u);
87 render_target.SetStencilAttachment(std::nullopt);
88 }
89
90 auto entity_pass_target = EntityPassTarget(render_target, false, true);
91
92 auto color0 = entity_pass_target.GetRenderTarget()
93 .GetColorAttachments()
94 .find(0u)
95 ->second;
96 auto msaa_tex = color0.texture;
97 auto resolve_tex = color0.resolve_texture;
98
99 ASSERT_EQ(msaa_tex, resolve_tex);
100
101 entity_pass_target.Flip(
102 *content_context->GetContext()->GetResourceAllocator());
103
104 color0 = entity_pass_target.GetRenderTarget()
105 .GetColorAttachments()
106 .find(0u)
107 ->second;
108
109 ASSERT_NE(msaa_tex, color0.texture);
110 ASSERT_NE(resolve_tex, color0.resolve_texture);
111 ASSERT_EQ(color0.texture, color0.resolve_texture);
112 }

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

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()
35 .GetColorAttachments()
36 .find(0u)
37 ->second;
38 auto msaa_tex = color0.texture;
39 auto resolve_tex = color0.resolve_texture;
40
41 entity_pass_target.Flip(
42 *content_context->GetContext()->GetResourceAllocator());
43
44 color0 = entity_pass_target.GetRenderTarget()
45 .GetColorAttachments()
46 .find(0u)
47 ->second;
48
49 ASSERT_EQ(msaa_tex, color0.texture);
50 ASSERT_NE(resolve_tex, color0.resolve_texture);
51 }

## ◆ TEST_P() [280/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | AdvancedBlendCoverageHintIsNotResetByEntityPass |
| ) |  |

Definition at line 2634 of file entity_unittests.cc.

2634 {
2635 if (GetContext()->GetCapabilities()->SupportsFramebufferFetch()) {
2636 GTEST_SKIP() << "Backends that support framebuffer fetch dont use coverage "
2637 "for advanced blends.";
2638 }
2639
2640 auto contents = std::make_shared<SolidColorContents>();
2641 contents->SetGeometry(Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100)));
2642 contents->SetColor(Color::Red());
2643
2644 Entity entity;
2645 entity.SetTransform(Matrix::MakeScale(Vector3(2, 2, 1)));
2646 entity.SetBlendMode(BlendMode::kColorBurn);
2647 entity.SetContents(contents);
2648
2649 auto coverage = entity.GetCoverage();
2650 EXPECT_TRUE(coverage.has_value());
2651
2652 auto pass = std::make_unique<EntityPass>();
2653 std::shared_ptr<RenderTargetCache> render_target_allocator =
2654 std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
2655 auto stencil_config = RenderTarget::AttachmentConfig{
2656 .storage_mode = StorageMode::kDevicePrivate,
2657 .load_action = LoadAction::kClear,
2658 .store_action = StoreAction::kDontCare,
2659 .clear_color = Color::BlackTransparent()};
2660 auto rt = render_target_allocator->CreateOffscreen(
2661 *GetContext(), ISize::MakeWH(1000, 1000),
2662 /*mip_count=*/1, "Offscreen", RenderTarget::kDefaultColorAttachmentConfig,
2663 stencil_config);
2664 auto content_context = ContentContext(
2665 GetContext(), TypographerContextSkia::Make(), render_target_allocator);
2666 pass->AddEntity(std::move(entity));
2667
2668 EXPECT_TRUE(pass->Render(content_context, rt));
2669
2670 auto contains_size = [&render_target_allocator](ISize size) -> bool {
2671 return std::find_if(render_target_allocator->GetRenderTargetDataBegin(),
2672 render_target_allocator->GetRenderTargetDataEnd(),
2673 [&size](const auto& data) {
2674 return data.config.size == size;
2675 }) != render_target_allocator->GetRenderTargetDataEnd();
2676 };
2677
2678 EXPECT_TRUE(contains_size(ISize(1000, 1000)))
2679 << "The root texture wasn't allocated";
2680 EXPECT_TRUE(contains_size(ISize(200, 200)))
2681 << "The ColorBurned texture wasn't allocated (100x100 scales up 2x)";
2682 }

References impeller::Color::BlackTransparent(), impeller::Entity::GetCoverage(), impeller::kClear, impeller::kColorBurn, impeller::RenderTarget::kDefaultColorAttachmentConfig, impeller::kDevicePrivate, impeller::kDontCare, impeller::TypographerContextSkia::Make(), impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::TSize< int64_t >::MakeWH(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::RenderTarget::AttachmentConfig::storage_mode.

## ◆ TEST_P() [281/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | AtlasContentsSubAtlas |
| ) |  |

Definition at line 2030 of file entity_unittests.cc.

2030 {
2031 auto boston = CreateTextureForFixture("boston.jpg");
2032
2033 {
2034 auto contents = std::make_shared<AtlasContents>();
2035 contents->SetBlendMode(BlendMode::kSourceOver);
2036 contents->SetTexture(boston);
2037 contents->SetColors({
2038 Color::Red(),
2039 Color::Red(),
2040 Color::Red(),
2041 });
2042 contents->SetTextureCoordinates({
2043 Rect::MakeLTRB(0, 0, 10, 10),
2044 Rect::MakeLTRB(0, 0, 10, 10),
2045 Rect::MakeLTRB(0, 0, 10, 10),
2046 });
2047 contents->SetTransforms({
2048 Matrix::MakeTranslation(Vector2(0, 0)),
2049 Matrix::MakeTranslation(Vector2(100, 100)),
2050 Matrix::MakeTranslation(Vector2(200, 200)),
2051 });
2052
2053 // Since all colors and sample rects are the same, there should
2054 // only be a single entry in the sub atlas.
2055 auto subatlas = contents->GenerateSubAtlas();
2056 ASSERT_EQ(subatlas->sub_texture_coords.size(), 1u);
2057 }
2058
2059 {
2060 auto contents = std::make_shared<AtlasContents>();
2061 contents->SetBlendMode(BlendMode::kSourceOver);
2062 contents->SetTexture(boston);
2063 contents->SetColors({
2064 Color::Red(),
2065 Color::Green(),
2066 Color::Blue(),
2067 });
2068 contents->SetTextureCoordinates({
2069 Rect::MakeLTRB(0, 0, 10, 10),
2070 Rect::MakeLTRB(0, 0, 10, 10),
2071 Rect::MakeLTRB(0, 0, 10, 10),
2072 });
2073 contents->SetTransforms({
2074 Matrix::MakeTranslation(Vector2(0, 0)),
2075 Matrix::MakeTranslation(Vector2(100, 100)),
2076 Matrix::MakeTranslation(Vector2(200, 200)),
2077 });
2078
2079 // Since all colors are different, there are three entires.
2080 auto subatlas = contents->GenerateSubAtlas();
2081 ASSERT_EQ(subatlas->sub_texture_coords.size(), 3u);
2082
2083 // The translations are kept but the sample rects point into
2084 // different parts of the sub atlas.
2085 ASSERT_EQ(subatlas->result_texture_coords[0], Rect::MakeXYWH(0, 0, 10, 10));
2086 ASSERT_EQ(subatlas->result_texture_coords[1],
2087 Rect::MakeXYWH(11, 0, 10, 10));
2088 ASSERT_EQ(subatlas->result_texture_coords[2],
2089 Rect::MakeXYWH(22, 0, 10, 10));
2090 }
2091 }

References impeller::Color::Blue(), impeller::Color::Green(), impeller::kSourceOver, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Color::Red().

## ◆ TEST_P() [282/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BezierCircleScaled |
| ) |  |

Definition at line 989 of file entity_unittests.cc.

989 {
990 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
991 static float scale = 20;
992
993 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
994 ImGui::SliderFloat("Scale", &scale, 1, 100);
995 ImGui::End();
996
997 Entity entity;
998 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
999 auto path = PathBuilder{}
1000 .MoveTo({97.325, 34.818})
1001 .CubicCurveTo({98.50862885295136, 34.81812293973836},
1002 {99.46822048142015, 33.85863261475589},
1003 {99.46822048142015, 32.67499810206613})
1004 .CubicCurveTo({99.46822048142015, 31.491363589376355},
1005 {98.50862885295136, 30.53187326439389},
1006 {97.32499434685802, 30.531998226542708})
1007 .CubicCurveTo({96.14153655073771, 30.532123170035373},
1008 {95.18222070648729, 31.491540299350355},
1009 {95.18222070648729, 32.67499810206613})
1010 .CubicCurveTo({95.18222070648729, 33.85845590478189},
1011 {96.14153655073771, 34.81787303409686},
1012 {97.32499434685802, 34.81799797758954})
1013 .Close()
1014 .TakePath();
1015 entity.SetTransform(
1016 Matrix::MakeScale({scale, scale, 1.0}).Translate({-90, -20, 0}));
1017 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
1018 return entity.Render(context, pass);
1019 };
1020 ASSERT_TRUE(OpenPlaygroundHere(callback));
1021 }

References impeller::Close(), impeller::SolidColorContents::Make(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::Render(), scale, impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [283/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BlendingModeOptions |
| ) |  |

Definition at line 861 of file entity_unittests.cc.

861 {
862 std::vector<const char*> blend_mode_names;
863 std::vector<BlendMode> blend_mode_values;
864 {
865 // Force an exhausiveness check with a switch. When adding blend modes,
866 // update this switch with a new name/value to make it selectable in the
867 // test GUI.
868
869 const BlendMode b{};
870 static_assert(b == BlendMode::kClear); // Ensure the first item in
871 // the switch is the first
872 // item in the enum.
873 static_assert(Entity::kLastPipelineBlendMode == BlendMode::kModulate);
874 switch (b) {
875 case BlendMode::kClear:
876 blend_mode_names.push_back("Clear");
877 blend_mode_values.push_back(BlendMode::kClear);
878 case BlendMode::kSource:
879 blend_mode_names.push_back("Source");
880 blend_mode_values.push_back(BlendMode::kSource);
881 case BlendMode::kDestination:
882 blend_mode_names.push_back("Destination");
883 blend_mode_values.push_back(BlendMode::kDestination);
884 case BlendMode::kSourceOver:
885 blend_mode_names.push_back("SourceOver");
886 blend_mode_values.push_back(BlendMode::kSourceOver);
887 case BlendMode::kDestinationOver:
888 blend_mode_names.push_back("DestinationOver");
889 blend_mode_values.push_back(BlendMode::kDestinationOver);
890 case BlendMode::kSourceIn:
891 blend_mode_names.push_back("SourceIn");
892 blend_mode_values.push_back(BlendMode::kSourceIn);
893 case BlendMode::kDestinationIn:
894 blend_mode_names.push_back("DestinationIn");
895 blend_mode_values.push_back(BlendMode::kDestinationIn);
896 case BlendMode::kSourceOut:
897 blend_mode_names.push_back("SourceOut");
898 blend_mode_values.push_back(BlendMode::kSourceOut);
899 case BlendMode::kDestinationOut:
900 blend_mode_names.push_back("DestinationOut");
901 blend_mode_values.push_back(BlendMode::kDestinationOut);
902 case BlendMode::kSourceATop:
903 blend_mode_names.push_back("SourceATop");
904 blend_mode_values.push_back(BlendMode::kSourceATop);
905 case BlendMode::kDestinationATop:
906 blend_mode_names.push_back("DestinationATop");
907 blend_mode_values.push_back(BlendMode::kDestinationATop);
908 case BlendMode::kXor:
909 blend_mode_names.push_back("Xor");
910 blend_mode_values.push_back(BlendMode::kXor);
911 case BlendMode::kPlus:
912 blend_mode_names.push_back("Plus");
913 blend_mode_values.push_back(BlendMode::kPlus);
914 case BlendMode::kModulate:
915 blend_mode_names.push_back("Modulate");
916 blend_mode_values.push_back(BlendMode::kModulate);
917 };
918 }
919
920 auto callback = [&](ContentContext& context, RenderPass& pass) {
921 auto world_matrix = Matrix::MakeScale(GetContentScale());
922 auto draw_rect = [&context, &pass, &world_matrix](
923 Rect rect, Color color, BlendMode blend_mode) -> bool {
924 using VS = SolidFillPipeline::VertexShader;
925
926 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
927 {
928 auto r = rect.GetLTRB();
929 vtx_builder.AddVertices({
930 {Point(r[0], r[1])},
931 {Point(r[2], r[1])},
932 {Point(r[2], r[3])},
933 {Point(r[0], r[1])},
934 {Point(r[2], r[3])},
935 {Point(r[0], r[3])},
936 });
937 }
938
939 pass.SetCommandLabel("Blended Rectangle");
940 auto options = OptionsFromPass(pass);
941 options.blend_mode = blend_mode;
942 options.primitive_type = PrimitiveType::kTriangle;
943 pass.SetPipeline(context.GetSolidFillPipeline(options));
944 pass.SetVertexBuffer(
945 vtx_builder.CreateVertexBuffer(context.GetTransientsBuffer()));
946
947 VS::FrameInfo frame_info;
948 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
949 frame_info.color = color.Premultiply();
950 VS::BindFrameInfo(
951 pass, context.GetTransientsBuffer().EmplaceUniform(frame_info));
952
953 return pass.Draw().ok();
954 };
955
956 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
957 static Color color1(1, 0, 0, 0.5), color2(0, 1, 0, 0.5);
958 ImGui::ColorEdit4("Color 1", reinterpret_cast<float*>(&color1));
959 ImGui::ColorEdit4("Color 2", reinterpret_cast<float*>(&color2));
960 static int current_blend_index = 3;
961 ImGui::ListBox("Blending mode", &current_blend_index,
962 blend_mode_names.data(), blend_mode_names.size());
963 ImGui::End();
964
965 BlendMode selected_mode = blend_mode_values[current_blend_index];
966
967 Point a, b, c, d;
968 static PlaygroundPoint point_a(Point(400, 100), 20, Color::White());
969 static PlaygroundPoint point_b(Point(200, 300), 20, Color::White());
970 std::tie(a, b) = DrawPlaygroundLine(point_a, point_b);
971 static PlaygroundPoint point_c(Point(470, 190), 20, Color::White());
972 static PlaygroundPoint point_d(Point(270, 390), 20, Color::White());
973 std::tie(c, d) = DrawPlaygroundLine(point_c, point_d);
974
975 bool result = true;
976 result = result &&
977 draw_rect(Rect::MakeXYWH(0, 0, pass.GetRenderTargetSize().width,
978 pass.GetRenderTargetSize().height),
979 Color(), BlendMode::kClear);
980 result = result && draw_rect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), color1,
981 BlendMode::kSourceOver);
982 result = result && draw_rect(Rect::MakeLTRB(c.x, c.y, d.x, d.y), color2,
983 selected_mode);
984 return result;
985 };
986 ASSERT_TRUE(OpenPlaygroundHere(callback));
987 }

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::kDestination, impeller::kDestinationATop, impeller::kDestinationIn, impeller::kDestinationOut, impeller::kDestinationOver, impeller::Entity::kLastPipelineBlendMode, impeller::kModulate, impeller::kPlus, impeller::kSource, impeller::kSourceATop, impeller::kSourceIn, impeller::kSourceOut, impeller::kSourceOver, 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() [284/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BorderMaskBlurCoverageIsCorrect |
| ) |  |

Definition at line 1390 of file entity_unittests.cc.

1390 {
1391 auto fill = std::make_shared<SolidColorContents>();
1392 fill->SetGeometry(Geometry::MakeFillPath(
1393 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1394 fill->SetColor(Color::CornflowerBlue());
1395 auto border_mask_blur = FilterContents::MakeBorderMaskBlur(
1396 FilterInput::Make(fill), Radius{3}, Radius{4});
1397
1398 {
1399 Entity e;
1400 e.SetTransform(Matrix());
1401 auto actual = border_mask_blur->GetCoverage(e);
1402 auto expected = Rect::MakeXYWH(-3, -4, 306, 408);
1403 ASSERT_TRUE(actual.has_value());
1404 ASSERT_RECT_NEAR(actual.value(), expected);
1405 }
1406
1407 {
1408 Entity e;
1409 e.SetTransform(Matrix::MakeRotationZ(Radians{kPi / 4}));
1410 auto actual = border_mask_blur->GetCoverage(e);
1411 auto expected = Rect::MakeXYWH(-287.792, -4.94975, 504.874, 504.874);
1412 ASSERT_TRUE(actual.has_value());
1413 ASSERT_RECT_NEAR(actual.value(), expected);
1414 }
1415 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanComputeGeometryForEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2816 of file entity_unittests.cc.

2816 {
2817 PathBuilder builder = {};
2818 builder.AddRect(Rect::MakeLTRB(0, 0, 0, 0));
2819 Path path = builder.TakePath();
2820
2821 EXPECT_TRUE(path.GetBoundingBox()->IsEmpty());
2822
2823 auto geom = Geometry::MakeFillPath(path);
2824
2825 Entity entity;
2826 RenderTarget target =
2827 GetContentContext()->GetRenderTargetCache()->CreateOffscreen(
2828 *GetContext(), {1, 1}, 1u);
2829 testing::MockRenderPass render_pass(GetContext(), target);
2830 auto position_result =
2831 geom->GetPositionBuffer(*GetContentContext(), entity, render_pass);
2832
2833 auto uv_result =
2834 geom->GetPositionUVBuffer(Rect::MakeLTRB(0, 0, 100, 100), Matrix(),
2835 *GetContentContext(), entity, render_pass);
2836
2837 EXPECT_EQ(position_result.vertex_buffer.vertex_count, 0u);
2838 EXPECT_EQ(uv_result.vertex_buffer.vertex_count, 0u);
2839
2840 EXPECT_EQ(geom->GetResultMode(), GeometryResult::Mode::kNormal);
2841 }

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

## ◆ TEST_P() [286/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanCreateEntity |
| ) |  |

Definition at line 70 of file entity_unittests.cc.

70 {
71 Entity entity;
72 ASSERT_TRUE(entity.GetTransform().IsIdentity());
73 }

References impeller::Entity::GetTransform(), and impeller::Matrix::IsIdentity().

## ◆ TEST_P() [287/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawCorrectlyWithRotatedTransform |
| ) |  |

Definition at line 545 of file entity_unittests.cc.

545 {
546 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
547 const char* input_axis[] = {"X", "Y", "Z"};
548 static int rotation_axis_index = 0;
549 static float rotation = 0;
550 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
551 ImGui::SliderFloat("Rotation", &rotation, -kPi, kPi);
552 ImGui::Combo("Rotation Axis", &rotation_axis_index, input_axis,
553 sizeof(input_axis) / sizeof(char*));
554 Matrix rotation_matrix;
555 switch (rotation_axis_index) {
556 case 0:
557 rotation_matrix = Matrix::MakeRotationX(Radians(rotation));
558 break;
559 case 1:
560 rotation_matrix = Matrix::MakeRotationY(Radians(rotation));
561 break;
562 case 2:
563 rotation_matrix = Matrix::MakeRotationZ(Radians(rotation));
564 break;
565 default:
566 rotation_matrix = Matrix{};
567 break;
568 }
569
570 if (ImGui::Button("Reset")) {
571 rotation = 0;
572 }
573 ImGui::End();
574 Matrix current_transform =
575 Matrix::MakeScale(GetContentScale())
576 .MakeTranslation(
577 Vector3(Point(pass.GetRenderTargetSize().width / 2.0,
578 pass.GetRenderTargetSize().height / 2.0)));
579 Matrix result_transform = current_transform * rotation_matrix;
580 Path path =
581 PathBuilder{}.AddRect(Rect::MakeXYWH(-300, -400, 600, 800)).TakePath();
582
583 Entity entity;
584 entity.SetTransform(result_transform);
585 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
586 return entity.Render(context, pass);
587 };
588 ASSERT_TRUE(OpenPlaygroundHere(callback));
589 }

References impeller::PathBuilder::AddRect(), impeller::kPi, impeller::SolidColorContents::Make(), 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() [288/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawRect |
| ) |  |

Definition at line 264 of file entity_unittests.cc.

264 {
265 auto contents = std::make_shared<SolidColorContents>();
266 contents->SetGeometry(Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100)));
267 contents->SetColor(Color::Red());
268
269 Entity entity;
270 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
271 entity.SetContents(contents);
272
273 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
274 }

References impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [289/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawRRect |
| ) |  |

Definition at line 276 of file entity_unittests.cc.

276 {
277 auto contents = std::make_shared<SolidColorContents>();
278 auto path = PathBuilder{}
279 .SetConvexity(Convexity::kConvex)
280 .AddRoundedRect(Rect::MakeXYWH(100, 100, 100, 100), 10.0)
281 .TakePath();
282 contents->SetGeometry(Geometry::MakeFillPath(path));
283 contents->SetColor(Color::Red());
284
285 Entity entity;
286 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
287 entity.SetContents(contents);
288
289 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
290 }

References impeller::PathBuilder::AddRoundedRect(), impeller::kConvex, impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Entity::SetContents(), impeller::PathBuilder::SetConvexity(), impeller::Entity::SetTransform(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [290/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanRenderEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2843 of file entity_unittests.cc.

2843 {
2844 PathBuilder builder = {};
2845 builder.AddRect(Rect::MakeLTRB(0, 0, 0, 0));
2846 Path path = builder.TakePath();
2847
2848 EXPECT_TRUE(path.GetBoundingBox()->IsEmpty());
2849
2850 auto contents = std::make_shared<SolidColorContents>();
2851 contents->SetGeometry(Geometry::MakeFillPath(path));
2852 contents->SetColor(Color::Red());
2853
2854 Entity entity;
2855 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2856 entity.SetContents(contents);
2857
2858 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2859 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ClipContentsGetClipCoverageIsCorrect |
| ) |  |

Definition at line 1726 of file entity_unittests.cc.

1726 {
1727 // Intersection: No stencil coverage, no geometry.
1728 {
1729 auto clip = std::make_shared<ClipContents>();
1730 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1731 auto result = clip->GetClipCoverage(Entity{}, Rect{});
1732
1733 ASSERT_FALSE(result.coverage.has_value());
1734 }
1735
1736 // Intersection: No stencil coverage, with geometry.
1737 {
1738 auto clip = std::make_shared<ClipContents>();
1739 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1740 clip->SetGeometry(Geometry::MakeFillPath(
1741 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1742 auto result = clip->GetClipCoverage(Entity{}, Rect{});
1743
1744 ASSERT_FALSE(result.coverage.has_value());
1745 }
1746
1747 // Intersection: With stencil coverage, no geometry.
1748 {
1749 auto clip = std::make_shared<ClipContents>();
1750 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1751 auto result =
1752 clip->GetClipCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1753
1754 ASSERT_FALSE(result.coverage.has_value());
1755 }
1756
1757 // Intersection: With stencil coverage, with geometry.
1758 {
1759 auto clip = std::make_shared<ClipContents>();
1760 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1761 clip->SetGeometry(Geometry::MakeFillPath(
1762 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 50, 50)).TakePath()));
1763 auto result =
1764 clip->GetClipCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1765
1766 ASSERT_TRUE(result.coverage.has_value());
1767 ASSERT_RECT_NEAR(result.coverage.value(), Rect::MakeLTRB(0, 0, 50, 50));
1768 ASSERT_EQ(result.type, Contents::ClipCoverage::Type::kAppend);
1769 }
1770
1771 // Difference: With stencil coverage, with geometry.
1772 {
1773 auto clip = std::make_shared<ClipContents>();
1774 clip->SetClipOperation(Entity::ClipOperation::kDifference);
1775 clip->SetGeometry(Geometry::MakeFillPath(
1776 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 50, 50)).TakePath()));
1777 auto result =
1778 clip->GetClipCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1779
1780 ASSERT_TRUE(result.coverage.has_value());
1781 ASSERT_RECT_NEAR(result.coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
1782 ASSERT_EQ(result.type, Contents::ClipCoverage::Type::kAppend);
1783 }
1784 }

References impeller::PathBuilder::AddRect(), ASSERT_RECT_NEAR, impeller::Contents::ClipCoverage::kAppend, impeller::Entity::kDifference, impeller::Entity::kIntersect, impeller::Geometry::MakeFillPath(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [292/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ClipContentsShouldRenderIsCorrect |
| ) |  |

Definition at line 1702 of file entity_unittests.cc.

1702 {
1703 // For clip ops, `ShouldRender` should always return true.
1704
1705 // Clip.
1706 {
1707 auto clip = std::make_shared<ClipContents>();
1708 ASSERT_TRUE(clip->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1709 clip->SetGeometry(Geometry::MakeFillPath(
1710 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1711 ASSERT_TRUE(clip->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1712 ASSERT_TRUE(
1713 clip->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1714 }
1715
1716 // Clip restore.
1717 {
1718 auto restore = std::make_shared<ClipRestoreContents>();
1719 ASSERT_TRUE(
1720 restore->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1721 ASSERT_TRUE(
1722 restore->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1723 }
1724 }

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

## ◆ TEST_P() [293/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterContentsWithLargeGeometry |
| ) |  |

Definition at line 2607 of file entity_unittests.cc.

2607 {
2608 Entity entity;
2609 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2610 auto src_contents = std::make_shared<SolidColorContents>();
2611 src_contents->SetGeometry(
2612 Geometry::MakeRect(Rect::MakeLTRB(-300, -500, 30000, 50000)));
2613 src_contents->SetColor(Color::Red());
2614
2615 auto dst_contents = std::make_shared<SolidColorContents>();
2616 dst_contents->SetGeometry(
2617 Geometry::MakeRect(Rect::MakeLTRB(300, 500, 20000, 30000)));
2618 dst_contents->SetColor(Color::Blue());
2619
2620 auto contents = ColorFilterContents::MakeBlend(
2621 BlendMode::kSourceOver, {FilterInput::Make(dst_contents, false),
2622 FilterInput::Make(src_contents, false)});
2623 entity.SetContents(std::move(contents));
2624 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2625 }

References impeller::Color::Blue(), impeller::kSourceOver, 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() [294/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorAdvancedBlend |
| ) |  |

Definition at line 2426 of file entity_unittests.cc.

2426 {
2427 auto image = CreateTextureForFixture("boston.jpg");
2428 auto filter = ColorFilterContents::MakeBlend(
2429 BlendMode::kColorBurn, FilterInput::Make({image}), Color::Red());
2430
2431 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2432 Entity entity;
2433 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2434 Matrix::MakeTranslation({500, 300}) *
2435 Matrix::MakeScale(Vector2{0.5, 0.5}));
2436 entity.SetContents(filter);
2437 return entity.Render(context, pass);
2438 };
2439 ASSERT_TRUE(OpenPlaygroundHere(callback));
2440 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorClearBlend |
| ) |  |

Definition at line 2442 of file entity_unittests.cc.

2442 {
2443 auto image = CreateTextureForFixture("boston.jpg");
2444 auto filter = ColorFilterContents::MakeBlend(
2445 BlendMode::kClear, FilterInput::Make({image}), Color::Red());
2446
2447 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2448 Entity entity;
2449 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2450 Matrix::MakeTranslation({500, 300}) *
2451 Matrix::MakeScale(Vector2{0.5, 0.5}));
2452 entity.SetContents(filter);
2453 return entity.Render(context, pass);
2454 };
2455 ASSERT_TRUE(OpenPlaygroundHere(callback));
2456 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorDstBlend |
| ) |  |

Definition at line 2474 of file entity_unittests.cc.

2474 {
2475 auto image = CreateTextureForFixture("boston.jpg");
2476 auto filter = ColorFilterContents::MakeBlend(
2477 BlendMode::kDestination, FilterInput::Make({image}), Color::Red());
2478
2479 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2480 Entity entity;
2481 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2482 Matrix::MakeTranslation({500, 300}) *
2483 Matrix::MakeScale(Vector2{0.5, 0.5}));
2484 entity.SetContents(filter);
2485 return entity.Render(context, pass);
2486 };
2487 ASSERT_TRUE(OpenPlaygroundHere(callback));
2488 }

References impeller::kDestination, 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() [297/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcBlend |
| ) |  |

Definition at line 2458 of file entity_unittests.cc.

2458 {
2459 auto image = CreateTextureForFixture("boston.jpg");
2460 auto filter = ColorFilterContents::MakeBlend(
2461 BlendMode::kSource, FilterInput::Make({image}), Color::Red());
2462
2463 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2464 Entity entity;
2465 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2466 Matrix::MakeTranslation({500, 300}) *
2467 Matrix::MakeScale(Vector2{0.5, 0.5}));
2468 entity.SetContents(filter);
2469 return entity.Render(context, pass);
2470 };
2471 ASSERT_TRUE(OpenPlaygroundHere(callback));
2472 }

References impeller::kSource, 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() [298/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcInBlend |
| ) |  |

Definition at line 2490 of file entity_unittests.cc.

2490 {
2491 auto image = CreateTextureForFixture("boston.jpg");
2492 auto filter = ColorFilterContents::MakeBlend(
2493 BlendMode::kSourceIn, FilterInput::Make({image}), Color::Red());
2494
2495 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2496 Entity entity;
2497 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2498 Matrix::MakeTranslation({500, 300}) *
2499 Matrix::MakeScale(Vector2{0.5, 0.5}));
2500 entity.SetContents(filter);
2501 return entity.Render(context, pass);
2502 };
2503 ASSERT_TRUE(OpenPlaygroundHere(callback));
2504 }

References impeller::kSourceIn, 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() [299/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterCoverageIsCorrect |
| ) |  |

Definition at line 1839 of file entity_unittests.cc.

1839 {
1840 // Set up a simple color background.
1841 auto fill = std::make_shared<SolidColorContents>();
1842 fill->SetGeometry(Geometry::MakeFillPath(
1843 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1844 fill->SetColor(Color::Coral());
1845
1846 // Set the color matrix filter.
1847 ColorMatrix matrix = {
1848 1, 1, 1, 1, 1, //
1849 1, 1, 1, 1, 1, //
1850 1, 1, 1, 1, 1, //
1851 1, 1, 1, 1, 1, //
1852 };
1853
1854 auto filter =
1855 ColorFilterContents::MakeColorMatrix(FilterInput::Make(fill), matrix);
1856
1857 Entity e;
1858 e.SetTransform(Matrix());
1859
1860 // Confirm that the actual filter coverage matches the expected coverage.
1861 auto actual = filter->GetCoverage(e);
1862 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1863
1864 ASSERT_TRUE(actual.has_value());
1865 ASSERT_RECT_NEAR(actual.value(), expected);
1866 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterEditable |
| ) |  |

Definition at line 1868 of file entity_unittests.cc.

1868 {
1869 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
1870 ASSERT_TRUE(bay_bridge);
1871
1872 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1873 // UI state.
1874 static ColorMatrix color_matrix = {
1875 1, 0, 0, 0, 0, //
1876 0, 3, 0, 0, 0, //
1877 0, 0, 1, 0, 0, //
1878 0, 0, 0, 1, 0, //
1879 };
1880 static float offset[2] = {500, 400};
1881 static float rotation = 0;
1882 static float scale[2] = {0.65, 0.65};
1883 static float skew[2] = {0, 0};
1884
1885 // Define the ImGui
1886 ImGui::Begin("Color Matrix", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1887 {
1888 std::string label = "##1";
1889 for (int i = 0; i < 20; i += 5) {
1890 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
1891 &(color_matrix.array[i]), 5, nullptr, nullptr,
1892 "%.2f", 0);
1893 label[2]++;
1894 }
1895
1896 ImGui::SliderFloat2("Translation", &offset[0], 0,
1897 pass.GetRenderTargetSize().width);
1898 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1899 ImGui::SliderFloat2("Scale", &scale[0], 0, 3);
1900 ImGui::SliderFloat2("Skew", &skew[0], -3, 3);
1901 }
1902 ImGui::End();
1903
1904 // Set the color matrix filter.
1905 auto filter = ColorFilterContents::MakeColorMatrix(
1906 FilterInput::Make(bay_bridge), color_matrix);
1907
1908 // Define the entity with the color matrix filter.
1909 Entity entity;
1910 entity.SetTransform(
1911 Matrix::MakeScale(GetContentScale()) *
1912 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1913 Matrix::MakeRotationZ(Radians(rotation)) *
1914 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1915 Matrix::MakeSkew(skew[0], skew[1]) *
1916 Matrix::MakeTranslation(-Point(bay_bridge->GetSize()) / 2));
1917 entity.SetContents(filter);
1918 entity.Render(context, pass);
1919
1920 return true;
1921 };
1922
1923 ASSERT_TRUE(OpenPlaygroundHere(callback));
1924 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ConicalGradientContentsIsOpaque |
| ) |  |

Definition at line 2530 of file entity_unittests.cc.

2530 {
2531 ConicalGradientContents contents;
2532 contents.SetColors({Color::CornflowerBlue()});
2533 ASSERT_FALSE(contents.IsOpaque());
2534 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2535 ASSERT_FALSE(contents.IsOpaque());
2536 }

References impeller::Color::CornflowerBlue(), impeller::Contents::IsOpaque(), impeller::ConicalGradientContents::SetColors(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [302/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentContextOptionsHasReasonableHashFunctions |
| ) |  |

Definition at line 2722 of file entity_unittests.cc.

2722 {
2723 ContentContextOptions opts;
2724 auto hash_a = ContentContextOptions::Hash{}(opts);
2725
2726 opts.blend_mode = BlendMode::kColorBurn;
2727 auto hash_b = ContentContextOptions::Hash{}(opts);
2728
2729 opts.has_depth_stencil_attachments = false;
2730 auto hash_c = ContentContextOptions::Hash{}(opts);
2731
2732 opts.primitive_type = PrimitiveType::kPoint;
2733 auto hash_d = ContentContextOptions::Hash{}(opts);
2734
2735 EXPECT_NE(hash_a, hash_b);
2736 EXPECT_NE(hash_b, hash_c);
2737 EXPECT_NE(hash_c, hash_d);
2738 }

References impeller::ContentContextOptions::blend_mode, impeller::ContentContextOptions::has_depth_stencil_attachments, impeller::kColorBurn, impeller::kPoint, and impeller::ContentContextOptions::primitive_type.

## ◆ TEST_P() [303/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentsGetBoundsForEmptyPathReturnsNullopt |
| ) |  |

Definition at line 1331 of file entity_unittests.cc.

1331 {
1332 Entity entity;
1333 entity.SetContents(std::make_shared<SolidColorContents>());
1334 ASSERT_FALSE(entity.GetCoverage().has_value());
1335 }

References impeller::Entity::GetCoverage(), and impeller::Entity::SetContents().

## ◆ TEST_P() [304/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CoverageForStrokePathWithNegativeValuesInTransform |
| ) |  |

Definition at line 2506 of file entity_unittests.cc.

2506 {
2507 auto arrow_head = PathBuilder{}
2508 .MoveTo({50, 120})
2509 .LineTo({120, 190})
2510 .LineTo({190, 120})
2511 .TakePath();
2512 auto geometry = Geometry::MakeStrokePath(arrow_head, 15.0, 4.0, Cap::kRound,
2513 Join::kRound);
2514
2515 auto transform = Matrix::MakeTranslation({300, 300}) *
2516 Matrix::MakeRotationZ(Radians(kPiOver2));
2517 EXPECT_LT(transform.e[0][0], 0.f);
2518 auto coverage = geometry->GetCoverage(transform);
2519 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeXYWH(102.5, 342.5, 85, 155));
2520 }

References ASSERT_RECT_NEAR, impeller::kPiOver2, impeller::kRound, impeller::LineTo(), impeller::Matrix::MakeRotationZ(), impeller::Geometry::MakeStrokePath(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::MoveTo().

## ◆ TEST_P() [305/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveAndOverlapTest |
| ) |  |

Definition at line 591 of file entity_unittests.cc.

591 {
592 // Compare with https://fiddle.skia.org/c/7a05a3e186c65a8dfb732f68020aae06
593 Path path =
594 PathBuilder{}
595 .MoveTo({359.934, 96.6335})
596 .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
597 {354.673, 96.8895})
598 .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
599 {354.367, 96.9075})
600 .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
601 {349.259, 97.2355})
602 .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
603 {348.625, 97.2834})
604 .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
605 {343.789, 97.6722})
606 .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
607 {342.703, 97.7734})
608 .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
609 {338.246, 98.207})
610 .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
611 {336.612, 98.3894})
612 .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
613 {332.623, 98.8476})
614 .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
615 {332.237, 98.8982})
616 .LineTo({332.237, 102.601})
617 .LineTo({321.778, 102.601})
618 .LineTo({321.778, 100.382})
619 .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
620 {321.161, 100.476})
621 .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
622 {315.332, 101.479})
623 .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
624 {315.301, 101.484})
625 .LineTo({310.017, 105.94})
626 .LineTo({309.779, 105.427})
627 .LineTo({314.403, 101.651})
628 .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
629 {314.368, 101.658})
630 .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
631 {308.846, 102.748})
632 .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
633 .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
634 {303.425, 103.936})
635 .LineTo({299.105, 107.578})
636 .LineTo({298.867, 107.065})
637 .LineTo({302.394, 104.185})
638 .LineTo({302.412, 104.171})
639 .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
640 {299.344, 104.921})
641 .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
642 .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
643 {291.462, 106.979})
644 .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
645 {290.471, 107.257})
646 .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
647 {287.449, 108.139})
648 .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
649 {284.536, 109.035})
650 .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
651 {281.952, 109.859})
652 .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
653 {279.633, 110.638})
654 .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
655 {276.803, 111.607})
656 .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
657 {276.672, 111.653})
658 .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
659 {271.721, 113.463})
660 .LineTo({271.717, 113.449})
661 .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
662 {270.963, 113.628})
663 .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
664 {270.748, 113.682})
665 .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
666 {269.839, 113.926})
667 .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
668 {269.681, 113.972})
669 .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
670 {268.756, 114.239})
671 .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
672 {268.367, 114.354})
673 .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
674 {267.752, 114.54})
675 .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
676 {253.564, 119.252})
677 .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
678 {253.538, 119.261})
679 .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
680 {248.189, 121.131})
681 .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
682 .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
683 {245.975, 121.912})
684 .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
685 {244.698, 122.364})
686 .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
687 {242.794, 123.04})
688 .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
689 {240.961, 123.693})
690 .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
691 {240.052, 124.018})
692 .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
693 .LineTo({237.164, 125.003})
694 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
695 {235.81, 125.538})
696 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
697 {234.592, 125.977})
698 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
699 {234.59, 125.977})
700 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
701 {192.381, 141.429})
702 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
703 .LineTo({360, 160})
704 .LineTo({360, 119.256})
705 .LineTo({360, 106.332})
706 .LineTo({360, 96.6307})
707 .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
708 {359.934, 96.6335})
709 .Close()
710 .MoveTo({337.336, 124.143})
711 .CubicCurveTo({337.274, 122.359}, {338.903, 121.511},
712 {338.903, 121.511})
713 .CubicCurveTo({338.903, 121.511}, {338.96, 123.303},
714 {337.336, 124.143})
715 .Close()
716 .MoveTo({340.082, 121.849})
717 .CubicCurveTo({340.074, 121.917}, {340.062, 121.992},
718 {340.046, 122.075})
719 .CubicCurveTo({340.039, 122.109}, {340.031, 122.142},
720 {340.023, 122.177})
721 .CubicCurveTo({340.005, 122.26}, {339.98, 122.346},
722 {339.952, 122.437})
723 .CubicCurveTo({339.941, 122.473}, {339.931, 122.507},
724 {339.918, 122.544})
725 .CubicCurveTo({339.873, 122.672}, {339.819, 122.804},
726 {339.75, 122.938})
727 .CubicCurveTo({339.747, 122.944}, {339.743, 122.949},
728 {339.74, 122.955})
729 .CubicCurveTo({339.674, 123.08}, {339.593, 123.205},
730 {339.501, 123.328})
731 .CubicCurveTo({339.473, 123.366}, {339.441, 123.401},
732 {339.41, 123.438})
733 .CubicCurveTo({339.332, 123.534}, {339.243, 123.625},
734 {339.145, 123.714})
735 .CubicCurveTo({339.105, 123.75}, {339.068, 123.786},
736 {339.025, 123.821})
737 .CubicCurveTo({338.881, 123.937}, {338.724, 124.048},
738 {338.539, 124.143})
739 .CubicCurveTo({338.532, 123.959}, {338.554, 123.79},
740 {338.58, 123.626})
741 .CubicCurveTo({338.58, 123.625}, {338.58, 123.625}, {338.58, 123.625})
742 .CubicCurveTo({338.607, 123.455}, {338.65, 123.299},
743 {338.704, 123.151})
744 .CubicCurveTo({338.708, 123.14}, {338.71, 123.127},
745 {338.714, 123.117})
746 .CubicCurveTo({338.769, 122.971}, {338.833, 122.838},
747 {338.905, 122.712})
748 .CubicCurveTo({338.911, 122.702}, {338.916, 122.69200000000001},
749 {338.922, 122.682})
750 .CubicCurveTo({338.996, 122.557}, {339.072, 122.444},
751 {339.155, 122.34})
752 .CubicCurveTo({339.161, 122.333}, {339.166, 122.326},
753 {339.172, 122.319})
754 .CubicCurveTo({339.256, 122.215}, {339.339, 122.12},
755 {339.425, 122.037})
756 .CubicCurveTo({339.428, 122.033}, {339.431, 122.03},
757 {339.435, 122.027})
758 .CubicCurveTo({339.785, 121.687}, {340.106, 121.511},
759 {340.106, 121.511})
760 .CubicCurveTo({340.106, 121.511}, {340.107, 121.645},
761 {340.082, 121.849})
762 .Close()
763 .MoveTo({340.678, 113.245})
764 .CubicCurveTo({340.594, 113.488}, {340.356, 113.655},
765 {340.135, 113.775})
766 .CubicCurveTo({339.817, 113.948}, {339.465, 114.059},
767 {339.115, 114.151})
768 .CubicCurveTo({338.251, 114.379}, {337.34, 114.516},
769 {336.448, 114.516})
770 .CubicCurveTo({335.761, 114.516}, {335.072, 114.527},
771 {334.384, 114.513})
772 .CubicCurveTo({334.125, 114.508}, {333.862, 114.462},
773 {333.605, 114.424})
774 .CubicCurveTo({332.865, 114.318}, {332.096, 114.184},
775 {331.41, 113.883})
776 .CubicCurveTo({330.979, 113.695}, {330.442, 113.34},
777 {330.672, 112.813})
778 .CubicCurveTo({331.135, 111.755}, {333.219, 112.946},
779 {334.526, 113.833})
780 .CubicCurveTo({334.54, 113.816}, {334.554, 113.8}, {334.569, 113.784})
781 .CubicCurveTo({333.38, 112.708}, {331.749, 110.985},
782 {332.76, 110.402})
783 .CubicCurveTo({333.769, 109.82}, {334.713, 111.93},
784 {335.228, 113.395})
785 .CubicCurveTo({334.915, 111.889}, {334.59, 109.636},
786 {335.661, 109.592})
787 .CubicCurveTo({336.733, 109.636}, {336.408, 111.889},
788 {336.07, 113.389})
789 .CubicCurveTo({336.609, 111.93}, {337.553, 109.82},
790 {338.563, 110.402})
791 .CubicCurveTo({339.574, 110.984}, {337.942, 112.708},
792 {336.753, 113.784})
793 .CubicCurveTo({336.768, 113.8}, {336.782, 113.816},
794 {336.796, 113.833})
795 .CubicCurveTo({338.104, 112.946}, {340.187, 111.755},
796 {340.65, 112.813})
797 .CubicCurveTo({340.71, 112.95}, {340.728, 113.102},
798 {340.678, 113.245})
799 .Close()
800 .MoveTo({346.357, 106.771})
801 .CubicCurveTo({346.295, 104.987}, {347.924, 104.139},
802 {347.924, 104.139})
803 .CubicCurveTo({347.924, 104.139}, {347.982, 105.931},
804 {346.357, 106.771})
805 .Close()
806 .MoveTo({347.56, 106.771})
807 .CubicCurveTo({347.498, 104.987}, {349.127, 104.139},
808 {349.127, 104.139})
809 .CubicCurveTo({349.127, 104.139}, {349.185, 105.931},
810 {347.56, 106.771})
811 .Close()
812 .TakePath();
813 Entity entity;
814 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
815 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
816 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
817 }

References impeller::Close(), impeller::LineTo(), impeller::SolidColorContents::Make(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [306/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveTest |
| ) |  |

Definition at line 523 of file entity_unittests.cc.

523 {
524 // Compare with https://fiddle.skia.org/c/b3625f26122c9de7afe7794fcf25ead3
525 Path path =
526 PathBuilder{}
527 .MoveTo({237.164, 125.003})
528 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
529 {235.81, 125.538})
530 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
531 {234.592, 125.977})
532 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
533 {234.59, 125.977})
534 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
535 {192.381, 141.429})
536 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
537 .Close()
538 .TakePath();
539 Entity entity;
540 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
541 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
542 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
543 }

References impeller::Close(), impeller::SolidColorContents::Make(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [307/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DecalSpecializationAppliedToMorphologyFilter |
| ) |  |

Definition at line 2706 of file entity_unittests.cc.

2706 {
2707 auto content_context = GetContentContext();
2708 auto default_color_burn = content_context->GetMorphologyFilterPipeline({
2709 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2710 });
2711
2712 auto decal_supported = static_cast<Scalar>(
2713 GetContext()->GetCapabilities()->SupportsDecalSamplerAddressMode());
2714 std::vector<Scalar> expected_constants = {decal_supported};
2715 ASSERT_EQ(default_color_burn->GetDescriptor().GetSpecializationConstants(),
2716 expected_constants);
2717 }

References impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [308/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DoesNotCullEntitiesByDefault |
| ) |  |

Definition at line 1688 of file entity_unittests.cc.

1688 {
1689 auto fill = std::make_shared<SolidColorContents>();
1690 fill->SetColor(Color::CornflowerBlue());
1691 fill->SetGeometry(
1692 Geometry::MakeRect(Rect::MakeLTRB(-1000, -1000, -900, -900)));
1693
1694 Entity entity;
1695 entity.SetContents(fill);
1696
1697 // Even though the entity is offscreen, this should still render because we do
1698 // not compute the coverage intersection by default.
1699 EXPECT_TRUE(entity.ShouldRender(Rect::MakeLTRB(0, 0, 100, 100)));
1700 }

References impeller::Color::CornflowerBlue(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Entity::SetContents(), and impeller::Entity::ShouldRender().

## ◆ TEST_P() [309/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasNoColor |
| ) |  |

Definition at line 1417 of file entity_unittests.cc.

1417 {
1418 // Draws the image as four squares stiched together.
1419 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1420 auto size = atlas->GetSize();
1421 // Divide image into four quadrants.
1422 Scalar half_width = size.width / 2;
1423 Scalar half_height = size.height / 2;
1424 std::vector<Rect> texture_coordinates = {
1425 Rect::MakeLTRB(0, 0, half_width, half_height),
1426 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1427 Rect::MakeLTRB(0, half_height, half_width, size.height),
1428 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1429 // Position quadrants adjacent to eachother.
1430 std::vector<Matrix> transforms = {
1431 Matrix::MakeTranslation({0, 0, 0}),
1432 Matrix::MakeTranslation({half_width, 0, 0}),
1433 Matrix::MakeTranslation({0, half_height, 0}),
1434 Matrix::MakeTranslation({half_width, half_height, 0})};
1435 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1436
1437 contents->SetTransforms(std::move(transforms));
1438 contents->SetTextureCoordinates(std::move(texture_coordinates));
1439 contents->SetTexture(atlas);
1440 contents->SetBlendMode(BlendMode::kSource);
1441
1442 Entity e;
1443 e.SetTransform(Matrix::MakeScale(GetContentScale()));
1444 e.SetContents(contents);
1445
1446 ASSERT_TRUE(OpenPlaygroundHere(std::move(e)));
1447 }

References impeller::kSource, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [310/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasNoColorFullSize |
| ) |  |

Definition at line 1593 of file entity_unittests.cc.

1593 {
1594 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1595 auto size = atlas->GetSize();
1596 std::vector<Rect> texture_coordinates = {
1597 Rect::MakeLTRB(0, 0, size.width, size.height)};
1598 std::vector<Matrix> transforms = {Matrix::MakeTranslation({0, 0, 0})};
1599 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1600
1601 contents->SetTransforms(std::move(transforms));
1602 contents->SetTextureCoordinates(std::move(texture_coordinates));
1603 contents->SetTexture(atlas);
1604 contents->SetBlendMode(BlendMode::kSource);
1605
1606 Entity e;
1607 e.SetTransform(Matrix::MakeScale(GetContentScale()));
1608 e.SetContents(contents);
1609
1610 ASSERT_TRUE(OpenPlaygroundHere(std::move(e)));
1611 }

References impeller::kSource, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [311/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasUsesProvidedCullRectForCoverage |
| ) |  |

Definition at line 1520 of file entity_unittests.cc.

1520 {
1521 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1522 auto size = atlas->GetSize();
1523
1524 Scalar half_width = size.width / 2;
1525 Scalar half_height = size.height / 2;
1526 std::vector<Rect> texture_coordinates = {
1527 Rect::MakeLTRB(0, 0, half_width, half_height),
1528 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1529 Rect::MakeLTRB(0, half_height, half_width, size.height),
1530 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1531 std::vector<Matrix> transforms = {
1532 Matrix::MakeTranslation({0, 0, 0}),
1533 Matrix::MakeTranslation({half_width, 0, 0}),
1534 Matrix::MakeTranslation({0, half_height, 0}),
1535 Matrix::MakeTranslation({half_width, half_height, 0})};
1536
1537 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1538
1539 contents->SetTransforms(std::move(transforms));
1540 contents->SetTextureCoordinates(std::move(texture_coordinates));
1541 contents->SetTexture(atlas);
1542 contents->SetBlendMode(BlendMode::kSource);
1543
1544 auto transform = Matrix::MakeScale(GetContentScale());
1545 Entity e;
1546 e.SetTransform(transform);
1547 e.SetContents(contents);
1548
1549 ASSERT_EQ(contents->GetCoverage(e).value(),
1550 Rect::MakeSize(size).TransformBounds(transform));
1551
1552 contents->SetCullRect(Rect::MakeLTRB(0, 0, 10, 10));
1553
1554 ASSERT_EQ(contents->GetCoverage(e).value(),
1555 Rect::MakeLTRB(0, 0, 10, 10).TransformBounds(transform));
1556 }

References impeller::kSource, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeSize(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::TRect< T >::TransformBounds().

## ◆ TEST_P() [312/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasWithColorAdvanced |
| ) |  |

Definition at line 1449 of file entity_unittests.cc.

1449 {
1450 // Draws the image as four squares stiched together.
1451 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1452 auto size = atlas->GetSize();
1453 // Divide image into four quadrants.
1454 Scalar half_width = size.width / 2;
1455 Scalar half_height = size.height / 2;
1456 std::vector<Rect> texture_coordinates = {
1457 Rect::MakeLTRB(0, 0, half_width, half_height),
1458 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1459 Rect::MakeLTRB(0, half_height, half_width, size.height),
1460 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1461 // Position quadrants adjacent to eachother.
1462 std::vector<Matrix> transforms = {
1463 Matrix::MakeTranslation({0, 0, 0}),
1464 Matrix::MakeTranslation({half_width, 0, 0}),
1465 Matrix::MakeTranslation({0, half_height, 0}),
1466 Matrix::MakeTranslation({half_width, half_height, 0})};
1467 std::vector<Color> colors = {Color::Red(), Color::Green(), Color::Blue(),
1468 Color::Yellow()};
1469 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1470
1471 contents->SetTransforms(std::move(transforms));
1472 contents->SetTextureCoordinates(std::move(texture_coordinates));
1473 contents->SetTexture(atlas);
1474 contents->SetColors(colors);
1475 contents->SetBlendMode(BlendMode::kModulate);
1476
1477 Entity e;
1478 e.SetTransform(Matrix::MakeScale(GetContentScale()));
1479 e.SetContents(contents);
1480
1481 ASSERT_TRUE(OpenPlaygroundHere(std::move(e)));
1482 }

References impeller::Color::Blue(), impeller::Color::Green(), impeller::kModulate, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::Color::Yellow().

## ◆ TEST_P() [313/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasWithColorSimple |
| ) |  |

Definition at line 1484 of file entity_unittests.cc.

1484 {
1485 // Draws the image as four squares stiched together. Because blend modes
1486 // aren't implented this ends up as four solid color blocks.
1487 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1488 auto size = atlas->GetSize();
1489 // Divide image into four quadrants.
1490 Scalar half_width = size.width / 2;
1491 Scalar half_height = size.height / 2;
1492 std::vector<Rect> texture_coordinates = {
1493 Rect::MakeLTRB(0, 0, half_width, half_height),
1494 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1495 Rect::MakeLTRB(0, half_height, half_width, size.height),
1496 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1497 // Position quadrants adjacent to eachother.
1498 std::vector<Matrix> transforms = {
1499 Matrix::MakeTranslation({0, 0, 0}),
1500 Matrix::MakeTranslation({half_width, 0, 0}),
1501 Matrix::MakeTranslation({0, half_height, 0}),
1502 Matrix::MakeTranslation({half_width, half_height, 0})};
1503 std::vector<Color> colors = {Color::Red(), Color::Green(), Color::Blue(),
1504 Color::Yellow()};
1505 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1506
1507 contents->SetTransforms(std::move(transforms));
1508 contents->SetTextureCoordinates(std::move(texture_coordinates));
1509 contents->SetTexture(atlas);
1510 contents->SetColors(colors);
1511 contents->SetBlendMode(BlendMode::kSourceATop);
1512
1513 Entity e;
1514 e.SetTransform(Matrix::MakeScale(GetContentScale()));
1515 e.SetContents(contents);
1516
1517 ASSERT_TRUE(OpenPlaygroundHere(std::move(e)));
1518 }

References impeller::Color::Blue(), impeller::Color::Green(), impeller::kSourceATop, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::Color::Yellow().

## ◆ TEST_P() [314/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasWithOpacity |
| ) |  |

Definition at line 1558 of file entity_unittests.cc.

1558 {
1559 // Draws the image as four squares stiched together slightly
1560 // opaque
1561 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1562 auto size = atlas->GetSize();
1563 // Divide image into four quadrants.
1564 Scalar half_width = size.width / 2;
1565 Scalar half_height = size.height / 2;
1566 std::vector<Rect> texture_coordinates = {
1567 Rect::MakeLTRB(0, 0, half_width, half_height),
1568 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1569 Rect::MakeLTRB(0, half_height, half_width, size.height),
1570 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1571 // Position quadrants adjacent to eachother.
1572 std::vector<Matrix> transforms = {
1573 Matrix::MakeTranslation({0, 0, 0}),
1574 Matrix::MakeTranslation({half_width, 0, 0}),
1575 Matrix::MakeTranslation({0, half_height, 0}),
1576 Matrix::MakeTranslation({half_width, half_height, 0})};
1577
1578 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1579
1580 contents->SetTransforms(std::move(transforms));
1581 contents->SetTextureCoordinates(std::move(texture_coordinates));
1582 contents->SetTexture(atlas);
1583 contents->SetBlendMode(BlendMode::kSource);
1584 contents->SetAlpha(0.5);
1585
1586 Entity e;
1587 e.SetTransform(Matrix::MakeScale(GetContentScale()));
1588 e.SetContents(contents);
1589
1590 ASSERT_TRUE(OpenPlaygroundHere(std::move(e)));
1591 }

References impeller::kSource, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [315/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | EntityPassCanMergeSubpassIntoParent |
| ) |  |

Definition at line 187 of file entity_unittests.cc.

187 {
188 // Both a red and a blue box should appear if the pass merging has worked
189 // correctly.
190
191 EntityPass pass;
192 auto subpass = CreatePassWithRectPath(Rect::MakeLTRB(0, 0, 100, 100),
193 Rect::MakeLTRB(50, 50, 150, 150),
194 ContentBoundsPromise::kUnknown, true);
195 pass.AddSubpass(std::move(subpass));
196
197 Entity entity;
198 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
199 auto contents = std::make_unique<SolidColorContents>();
200 contents->SetGeometry(Geometry::MakeRect(Rect::MakeLTRB(100, 100, 200, 200)));
201 contents->SetColor(Color::Blue());
202 entity.SetContents(std::move(contents));
203
204 pass.AddEntity(std::move(entity));
205
206 ASSERT_TRUE(OpenPlaygroundHere(pass));
207 }

References impeller::EntityPass::AddEntity(), impeller::EntityPass::AddSubpass(), impeller::Color::Blue(), CreatePassWithRectPath(), impeller::kUnknown, impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [316/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | EntityPassCoverageRespectsCoverageLimit |
| ) |  |

Definition at line 209 of file entity_unittests.cc.

209 {
210 // Rect is drawn entirely in negative area.
211 auto pass = CreatePassWithRectPath(Rect::MakeLTRB(-200, -200, -100, -100),
212 std::nullopt);
213
214 // Without coverage limit.
215 {
216 auto pass_coverage = pass->GetElementsCoverage(std::nullopt);
217 ASSERT_TRUE(pass_coverage.has_value());
218 ASSERT_RECT_NEAR(pass_coverage.value(),
219 Rect::MakeLTRB(-200, -200, -100, -100));
220 }
221
222 // With limit that doesn't overlap.
223 {
224 auto pass_coverage =
225 pass->GetElementsCoverage(Rect::MakeLTRB(0, 0, 100, 100));
226 ASSERT_FALSE(pass_coverage.has_value());
227 }
228
229 // With limit that partially overlaps.
230 {
231 auto pass_coverage =
232 pass->GetElementsCoverage(Rect::MakeLTRB(-150, -150, 0, 0));
233 ASSERT_TRUE(pass_coverage.has_value());
234 ASSERT_RECT_NEAR(pass_coverage.value(),
235 Rect::MakeLTRB(-150, -150, -100, -100));
236 }
237 }

References ASSERT_RECT_NEAR, CreatePassWithRectPath(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [317/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | EntityPassRespectsUntrustedSubpassBoundsLimit |
| ) |  |

Definition at line 124 of file entity_unittests.cc.

124 {
125 EntityPass pass;
126
127 auto subpass0 = CreatePassWithRectPath(Rect::MakeLTRB(0, 0, 100, 100),
128 Rect::MakeLTRB(50, 50, 150, 150));
129 auto subpass1 = CreatePassWithRectPath(Rect::MakeLTRB(500, 500, 1000, 1000),
130 Rect::MakeLTRB(800, 800, 900, 900));
131
132 auto subpass0_coverage =
133 pass.GetSubpassCoverage(*subpass0.get(), std::nullopt);
134 ASSERT_TRUE(subpass0_coverage.has_value());
135 ASSERT_RECT_NEAR(subpass0_coverage.value(), Rect::MakeLTRB(50, 50, 100, 100));
136
137 auto subpass1_coverage =
138 pass.GetSubpassCoverage(*subpass1.get(), std::nullopt);
139 ASSERT_TRUE(subpass1_coverage.has_value());
140 ASSERT_RECT_NEAR(subpass1_coverage.value(),
141 Rect::MakeLTRB(800, 800, 900, 900));
142
143 pass.AddSubpass(std::move(subpass0));
144 pass.AddSubpass(std::move(subpass1));
145
146 auto coverage = pass.GetElementsCoverage(std::nullopt);
147 ASSERT_TRUE(coverage.has_value());
148 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(50, 50, 900, 900));
149 }

References impeller::EntityPass::AddSubpass(), ASSERT_RECT_NEAR, CreatePassWithRectPath(), impeller::EntityPass::GetElementsCoverage(), impeller::EntityPass::GetSubpassCoverage(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [318/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | EntityPassTrustsSnugSubpassBoundsLimit |
| ) |  |

Definition at line 151 of file entity_unittests.cc.

151 {
152 EntityPass pass;
153
154 auto subpass0 = //
155 CreatePassWithRectPath(Rect::MakeLTRB(10, 10, 90, 90),
156 Rect::MakeLTRB(5, 5, 95, 95),
157 ContentBoundsPromise::kContainsContents);
158 auto subpass1 = //
159 CreatePassWithRectPath(Rect::MakeLTRB(500, 500, 1000, 1000),
160 Rect::MakeLTRB(495, 495, 1005, 1005),
161 ContentBoundsPromise::kContainsContents);
162
163 auto subpass0_coverage =
164 pass.GetSubpassCoverage(*subpass0.get(), std::nullopt);
165 EXPECT_TRUE(subpass0_coverage.has_value());
166 // Result should be the overridden bounds
167 // (we lied about them being snug, but the property is respected)
168 EXPECT_RECT_NEAR(subpass0_coverage.value(), Rect::MakeLTRB(5, 5, 95, 95));
169
170 auto subpass1_coverage =
171 pass.GetSubpassCoverage(*subpass1.get(), std::nullopt);
172 EXPECT_TRUE(subpass1_coverage.has_value());
173 // Result should be the overridden bounds
174 // (we lied about them being snug, but the property is respected)
175 EXPECT_RECT_NEAR(subpass1_coverage.value(),
176 Rect::MakeLTRB(495, 495, 1005, 1005));
177
178 pass.AddSubpass(std::move(subpass0));
179 pass.AddSubpass(std::move(subpass1));
180
181 auto coverage = pass.GetElementsCoverage(std::nullopt);
182 EXPECT_TRUE(coverage.has_value());
183 // This result should be the union of the overridden bounds
184 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(5, 5, 1005, 1005));
185 }

References impeller::EntityPass::AddSubpass(), CreatePassWithRectPath(), EXPECT_RECT_NEAR, impeller::EntityPass::GetElementsCoverage(), impeller::EntityPass::GetSubpassCoverage(), impeller::kContainsContents, and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [319/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FailOnValidationError |
| ) |  |

Definition at line 2802 of file entity_unittests.cc.

2802 {
2803 if (GetParam() != PlaygroundBackend::kVulkan) {
2804 GTEST_SKIP() << "Validation is only fatal on Vulkan backend.";
2805 }
2806 EXPECT_DEATH(
2807 // The easiest way to trigger a validation error is to try to compile
2808 // a shader with an unsupported pixel format.
2809 GetContentContext()->GetBlendColorBurnPipeline({
2810 .color_attachment_pixel_format = PixelFormat::kUnknown,
2811 .has_depth_stencil_attachments = false,
2812 }),
2813 "");
2814 }

References impeller::kUnknown, and impeller::kVulkan.

## ◆ TEST_P() [320/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FillPathGeometryGetPositionBufferReturnsExpectedMode |
| ) |  |

Definition at line 2764 of file entity_unittests.cc.

2764 {
2765 RenderTarget target;
2766 testing::MockRenderPass mock_pass(GetContext(), target);
2767
2768 auto get_result = [this, &mock_pass](const Path& path) {
2769 auto geometry = Geometry::MakeFillPath(
2770 path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
2771 return geometry->GetPositionBuffer(*GetContentContext(), {}, mock_pass);
2772 };
2773
2774 // Convex path
2775 {
2776 GeometryResult result =
2777 get_result(PathBuilder{}
2778 .AddRect(Rect::MakeLTRB(0, 0, 100, 100))
2779 .SetConvexity(Convexity::kConvex)
2780 .TakePath());
2781 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
2782 }
2783
2784 // Concave path
2785 {
2786 Path path = PathBuilder{}
2787 .MoveTo({0, 0})
2788 .LineTo({100, 0})
2789 .LineTo({100, 100})
2790 .LineTo({50, 50})
2791 .Close()
2792 .TakePath();
2793 GeometryResult result = get_result(path);
2794 if constexpr (ContentContext::kEnableStencilThenCover) {
2795 EXPECT_EQ(result.mode, GeometryResult::Mode::kNonZero);
2796 } else {
2797 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
2798 }
2799 }
2800 }

References impeller::PathBuilder::AddRect(), impeller::Close(), impeller::kConvex, impeller::ContentContext::kEnableStencilThenCover, impeller::GeometryResult::kNonZero, impeller::GeometryResult::kNormal, impeller::LineTo(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::GeometryResult::mode, and impeller::PathBuilder::MoveTo().

## ◆ TEST_P() [321/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FilterCoverageRespectsCropRect |
| ) |  |

Definition at line 239 of file entity_unittests.cc.

239 {
240 auto image = CreateTextureForFixture("boston.jpg");
241 auto filter = ColorFilterContents::MakeBlend(BlendMode::kSoftLight,
242 FilterInput::Make({image}));
243
244 // Without the crop rect (default behavior).
245 {
246 auto actual = filter->GetCoverage({});
247 auto expected = Rect::MakeSize(image->GetSize());
248
249 ASSERT_TRUE(actual.has_value());
250 ASSERT_RECT_NEAR(actual.value(), expected);
251 }
252
253 // With the crop rect.
254 {
255 auto expected = Rect::MakeLTRB(50, 50, 100, 100);
256 filter->SetCoverageHint(expected);
257 auto actual = filter->GetCoverage({});
258
259 ASSERT_TRUE(actual.has_value());
260 ASSERT_RECT_NEAR(actual.value(), expected);
261 }
262 }

References ASSERT_RECT_NEAR, impeller::kSoftLight, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST_P() [322/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | Filters |
| ) |  |

Definition at line 1023 of file entity_unittests.cc.

1023 {
1024 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
1025 auto boston = CreateTextureForFixture("boston.jpg");
1026 auto kalimba = CreateTextureForFixture("kalimba.jpg");
1027 ASSERT_TRUE(bridge && boston && kalimba);
1028
1029 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1030 auto fi_bridge = FilterInput::Make(bridge);
1031 auto fi_boston = FilterInput::Make(boston);
1032 auto fi_kalimba = FilterInput::Make(kalimba);
1033
1034 std::shared_ptr<FilterContents> blend0 = ColorFilterContents::MakeBlend(
1035 BlendMode::kModulate, {fi_kalimba, fi_boston});
1036
1037 auto blend1 = ColorFilterContents::MakeBlend(
1038 BlendMode::kScreen,
1039 {FilterInput::Make(blend0), fi_bridge, fi_bridge, fi_bridge});
1040
1041 Entity entity;
1042 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1043 Matrix::MakeTranslation({500, 300}) *
1044 Matrix::MakeScale(Vector2{0.5, 0.5}));
1045 entity.SetContents(blend1);
1046 return entity.Render(context, pass);
1047 };
1048 ASSERT_TRUE(OpenPlaygroundHere(callback));
1049 }

References impeller::kModulate, impeller::kScreen, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [323/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GaussianBlurFilter |
| ) |  |

Definition at line 1051 of file entity_unittests.cc.

1051 {
1052 auto boston =
1053 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
1054 ASSERT_TRUE(boston);
1055
1056 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1057 const char* input_type_names[] = {"Texture", "Solid Color"};
1058 const char* blur_type_names[] = {"Image blur", "Mask blur"};
1059 const char* pass_variation_names[] = {"New"};
1060 const char* blur_style_names[] = {"Normal", "Solid", "Outer", "Inner"};
1061 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1062 const FilterContents::BlurStyle blur_styles[] = {
1063 FilterContents::BlurStyle::kNormal, FilterContents::BlurStyle::kSolid,
1064 FilterContents::BlurStyle::kOuter, FilterContents::BlurStyle::kInner};
1065 const Entity::TileMode tile_modes[] = {
1066 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
1067 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
1068
1069 // UI state.
1070 static int selected_input_type = 0;
1071 static Color input_color = Color::Black();
1072 static int selected_blur_type = 0;
1073 static int selected_pass_variation = 0;
1074 static bool combined_sigma = false;
1075 static float blur_amount_coarse[2] = {0, 0};
1076 static float blur_amount_fine[2] = {10, 10};
1077 static int selected_blur_style = 0;
1078 static int selected_tile_mode = 3;
1079 static Color cover_color(1, 0, 0, 0.2);
1080 static Color bounds_color(0, 1, 0, 0.1);
1081 static float offset[2] = {500, 400};
1082 static float rotation = 0;
1083 static float scale[2] = {0.65, 0.65};
1084 static float skew[2] = {0, 0};
1085 static float path_rect[4] = {0, 0,
1086 static_cast<float>(boston->GetSize().width),
1087 static_cast<float>(boston->GetSize().height)};
1088
1089 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1090 {
1091 ImGui::Combo("Input type", &selected_input_type, input_type_names,
1092 sizeof(input_type_names) / sizeof(char*));
1093 if (selected_input_type == 0) {
1094 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1095 } else {
1096 ImGui::ColorEdit4("Input color",
1097 reinterpret_cast<float*>(&input_color));
1098 }
1099 ImGui::Combo("Blur type", &selected_blur_type, blur_type_names,
1100 sizeof(blur_type_names) / sizeof(char*));
1101 if (selected_blur_type == 0) {
1102 ImGui::Combo("Pass variation", &selected_pass_variation,
1103 pass_variation_names,
1104 sizeof(pass_variation_names) / sizeof(char*));
1105 }
1106 ImGui::Checkbox("Combined sigma", &combined_sigma);
1107 if (combined_sigma) {
1108 ImGui::SliderFloat("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1109 ImGui::SliderFloat("Sigma (fine)", blur_amount_fine, 0, 10);
1110 blur_amount_coarse[1] = blur_amount_coarse[0];
1111 blur_amount_fine[1] = blur_amount_fine[0];
1112 } else {
1113 ImGui::SliderFloat2("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1114 ImGui::SliderFloat2("Sigma (fine)", blur_amount_fine, 0, 10);
1115 }
1116 ImGui::Combo("Blur style", &selected_blur_style, blur_style_names,
1117 sizeof(blur_style_names) / sizeof(char*));
1118 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1119 sizeof(tile_mode_names) / sizeof(char*));
1120 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1121 ImGui::ColorEdit4("Bounds color",
1122 reinterpret_cast<float*>(&bounds_color));
1123 ImGui::SliderFloat2("Translation", offset, 0,
1124 pass.GetRenderTargetSize().width);
1125 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1126 ImGui::SliderFloat2("Scale", scale, 0, 3);
1127 ImGui::SliderFloat2("Skew", skew, -3, 3);
1128 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1129 }
1130 ImGui::End();
1131
1132 auto blur_sigma_x = Sigma{blur_amount_coarse[0] + blur_amount_fine[0]};
1133 auto blur_sigma_y = Sigma{blur_amount_coarse[1] + blur_amount_fine[1]};
1134
1135 std::shared_ptr<Contents> input;
1136 Size input_size;
1137
1138 auto input_rect =
1139 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1140 if (selected_input_type == 0) {
1141 auto texture = std::make_shared<TextureContents>();
1142 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1143 texture->SetDestinationRect(input_rect);
1144 texture->SetTexture(boston);
1145 texture->SetOpacity(input_color.alpha);
1146
1147 input = texture;
1148 input_size = input_rect.GetSize();
1149 } else {
1150 auto fill = std::make_shared<SolidColorContents>();
1151 fill->SetColor(input_color);
1152 fill->SetGeometry(
1153 Geometry::MakeFillPath(PathBuilder{}.AddRect(input_rect).TakePath()));
1154
1155 input = fill;
1156 input_size = input_rect.GetSize();
1157 }
1158
1159 std::shared_ptr<FilterContents> blur;
1160 switch (selected_pass_variation) {
1161 case 0:
1162 blur = std::make_shared<GaussianBlurFilterContents>(
1163 blur_sigma_x.sigma, blur_sigma_y.sigma,
1164 tile_modes[selected_tile_mode], blur_styles[selected_blur_style],
1165 /*geometry=*/nullptr);
1166 blur->SetInputs({FilterInput::Make(input)});
1167 break;
1168 case 1:
1169 blur = FilterContents::MakeGaussianBlur(
1170 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1171 tile_modes[selected_tile_mode], blur_styles[selected_blur_style]);
1172 break;
1173 };
1174 FML_CHECK(blur);
1175
1176 auto mask_blur = FilterContents::MakeBorderMaskBlur(
1177 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1178 blur_styles[selected_blur_style]);
1179
1180 auto ctm = Matrix::MakeScale(GetContentScale()) *
1181 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1182 Matrix::MakeRotationZ(Radians(rotation)) *
1183 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1184 Matrix::MakeSkew(skew[0], skew[1]) *
1185 Matrix::MakeTranslation(-Point(input_size) / 2);
1186
1187 auto target_contents = selected_blur_type == 0 ? blur : mask_blur;
1188
1189 Entity entity;
1190 entity.SetContents(target_contents);
1191 entity.SetTransform(ctm);
1192
1193 entity.Render(context, pass);
1194
1195 // Renders a red "cover" rectangle that shows the original position of the
1196 // unfiltered input.
1197 Entity cover_entity;
1198 cover_entity.SetContents(SolidColorContents::Make(
1199 PathBuilder{}.AddRect(input_rect).TakePath(), cover_color));
1200 cover_entity.SetTransform(ctm);
1201
1202 cover_entity.Render(context, pass);
1203
1204 // Renders a green bounding rect of the target filter.
1205 Entity bounds_entity;
1206 std::optional<Rect> target_contents_coverage =
1207 target_contents->GetCoverage(entity);
1208 if (target_contents_coverage.has_value()) {
1209 bounds_entity.SetContents(SolidColorContents::Make(
1210 PathBuilder{}
1211 .AddRect(target_contents->GetCoverage(entity).value())
1212 .TakePath(),
1213 bounds_color));
1214 bounds_entity.SetTransform(Matrix());
1215
1216 bounds_entity.Render(context, pass);
1217 }
1218
1219 return true;
1220 };
1221 ASSERT_TRUE(OpenPlaygroundHere(callback));
1222 }

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::SolidColorContents::Make(), 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() [324/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GeometryBoundsAreTransformed |
| ) |  |

Definition at line 292 of file entity_unittests.cc.

292 {
293 auto geometry = Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100));
294 auto transform = Matrix::MakeScale({2.0, 2.0, 2.0});
295
296 ASSERT_RECT_NEAR(geometry->GetCoverage(transform).value(),
297 Rect::MakeXYWH(200, 200, 200, 200));
298 }

References ASSERT_RECT_NEAR, impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [325/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | InheritOpacityTest |
| ) |  |

Definition at line 2356 of file entity_unittests.cc.

2356 {
2357 Entity entity;
2358
2359 // Texture contents can always accept opacity.
2360 auto texture_contents = std::make_shared<TextureContents>();
2361 texture_contents->SetOpacity(0.5);
2362 ASSERT_TRUE(texture_contents->CanInheritOpacity(entity));
2363
2364 texture_contents->SetInheritedOpacity(0.5);
2365 ASSERT_EQ(texture_contents->GetOpacity(), 0.25);
2366 texture_contents->SetInheritedOpacity(0.5);
2367 ASSERT_EQ(texture_contents->GetOpacity(), 0.25);
2368
2369 // Solid color contents can accept opacity if their geometry
2370 // doesn't overlap.
2371 auto solid_color = std::make_shared<SolidColorContents>();
2372 solid_color->SetGeometry(
2373 Geometry::MakeRect(Rect::MakeLTRB(100, 100, 200, 200)));
2374 solid_color->SetColor(Color::Blue().WithAlpha(0.5));
2375
2376 ASSERT_TRUE(solid_color->CanInheritOpacity(entity));
2377
2378 solid_color->SetInheritedOpacity(0.5);
2379 ASSERT_EQ(solid_color->GetColor().alpha, 0.25);
2380 solid_color->SetInheritedOpacity(0.5);
2381 ASSERT_EQ(solid_color->GetColor().alpha, 0.25);
2382
2383 // Color source contents can accept opacity if their geometry
2384 // doesn't overlap.
2385 auto tiled_texture = std::make_shared<TiledTextureContents>();
2386 tiled_texture->SetGeometry(
2387 Geometry::MakeRect(Rect::MakeLTRB(100, 100, 200, 200)));
2388 tiled_texture->SetOpacityFactor(0.5);
2389
2390 ASSERT_TRUE(tiled_texture->CanInheritOpacity(entity));
2391
2392 tiled_texture->SetInheritedOpacity(0.5);
2393 ASSERT_EQ(tiled_texture->GetOpacityFactor(), 0.25);
2394 tiled_texture->SetInheritedOpacity(0.5);
2395 ASSERT_EQ(tiled_texture->GetOpacityFactor(), 0.25);
2396
2397 // Text contents can accept opacity if the text frames do not
2398 // overlap
2399 SkFont font = flutter::testing::CreateTestFontOfSize(30);
2400 auto blob = SkTextBlob::MakeFromString("A", font);
2401 auto frame = MakeTextFrameFromTextBlobSkia(blob);
2402 auto lazy_glyph_atlas =
2403 std::make_shared<LazyGlyphAtlas>(TypographerContextSkia::Make());
2404 lazy_glyph_atlas->AddTextFrame(*frame, 1.0f);
2405
2406 auto text_contents = std::make_shared<TextContents>();
2407 text_contents->SetTextFrame(frame);
2408 text_contents->SetColor(Color::Blue().WithAlpha(0.5));
2409
2410 ASSERT_TRUE(text_contents->CanInheritOpacity(entity));
2411
2412 text_contents->SetInheritedOpacity(0.5);
2413 ASSERT_EQ(text_contents->GetColor().alpha, 0.25);
2414 text_contents->SetInheritedOpacity(0.5);
2415 ASSERT_EQ(text_contents->GetColor().alpha, 0.25);
2416
2417 // Clips and restores trivially accept opacity.
2418 ASSERT_TRUE(ClipContents().CanInheritOpacity(entity));
2419 ASSERT_TRUE(ClipRestoreContents().CanInheritOpacity(entity));
2420
2421 // Runtime effect contents can't accept opacity.
2422 auto runtime_effect = std::make_shared<RuntimeEffectContents>();
2423 ASSERT_FALSE(runtime_effect->CanInheritOpacity(entity));
2424 }

References impeller::Color::Blue(), impeller::TypographerContextSkia::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [326/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearGradientContentsIsOpaque |
| ) |  |

Definition at line 2538 of file entity_unittests.cc.

2538 {
2539 LinearGradientContents contents;
2540 contents.SetColors({Color::CornflowerBlue()});
2541 ASSERT_TRUE(contents.IsOpaque());
2542 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2543 ASSERT_FALSE(contents.IsOpaque());
2544 contents.SetColors({Color::CornflowerBlue()});
2545 contents.SetTileMode(Entity::TileMode::kDecal);
2546 ASSERT_FALSE(contents.IsOpaque());
2547 }

References impeller::Color::CornflowerBlue(), impeller::LinearGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::LinearGradientContents::SetColors(), impeller::LinearGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [327/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilter |
| ) |  |

Definition at line 1947 of file entity_unittests.cc.

1947 {
1948 auto image = CreateTextureForFixture("kalimba.jpg");
1949 ASSERT_TRUE(image);
1950
1951 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1952 auto filtered =
1953 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(image));
1954
1955 // Define the entity that will serve as the control image as a Gaussian blur
1956 // filter with no filter at all.
1957 Entity entity_left;
1958 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1959 Matrix::MakeTranslation({100, 300}) *
1960 Matrix::MakeScale(Vector2{0.5, 0.5}));
1961 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1962 Sigma{0}, Sigma{0});
1963 entity_left.SetContents(unfiltered);
1964
1965 // Define the entity that will be filtered from linear to sRGB.
1966 Entity entity_right;
1967 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1968 Matrix::MakeTranslation({500, 300}) *
1969 Matrix::MakeScale(Vector2{0.5, 0.5}));
1970 entity_right.SetContents(filtered);
1971 return entity_left.Render(context, pass) &&
1972 entity_right.Render(context, pass);
1973 };
1974
1975 ASSERT_TRUE(OpenPlaygroundHere(callback));
1976 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilterCoverageIsCorrect |
| ) |  |

Definition at line 1926 of file entity_unittests.cc.

1926 {
1927 // Set up a simple color background.
1928 auto fill = std::make_shared<SolidColorContents>();
1929 fill->SetGeometry(Geometry::MakeFillPath(
1930 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1931 fill->SetColor(Color::MintCream());
1932
1933 auto filter =
1934 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(fill));
1935
1936 Entity e;
1937 e.SetTransform(Matrix());
1938
1939 // Confirm that the actual filter coverage matches the expected coverage.
1940 auto actual = filter->GetCoverage(e);
1941 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1942
1943 ASSERT_TRUE(actual.has_value());
1944 ASSERT_RECT_NEAR(actual.value(), expected);
1945 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | MorphologyFilter |
| ) |  |

Definition at line 1224 of file entity_unittests.cc.

1224 {
1225 auto boston = CreateTextureForFixture("boston.jpg");
1226 ASSERT_TRUE(boston);
1227
1228 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1229 const char* morphology_type_names[] = {"Dilate", "Erode"};
1230 const FilterContents::MorphType morphology_types[] = {
1231 FilterContents::MorphType::kDilate, FilterContents::MorphType::kErode};
1232 static Color input_color = Color::Black();
1233 // UI state.
1234 static int selected_morphology_type = 0;
1235 static float radius[2] = {20, 20};
1236 static Color cover_color(1, 0, 0, 0.2);
1237 static Color bounds_color(0, 1, 0, 0.1);
1238 static float offset[2] = {500, 400};
1239 static float rotation = 0;
1240 static float scale[2] = {0.65, 0.65};
1241 static float skew[2] = {0, 0};
1242 static float path_rect[4] = {0, 0,
1243 static_cast<float>(boston->GetSize().width),
1244 static_cast<float>(boston->GetSize().height)};
1245 static float effect_transform_scale = 1;
1246
1247 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1248 {
1249 ImGui::Combo("Morphology type", &selected_morphology_type,
1250 morphology_type_names,
1251 sizeof(morphology_type_names) / sizeof(char*));
1252 ImGui::SliderFloat2("Radius", radius, 0, 200);
1253 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1254 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1255 ImGui::ColorEdit4("Bounds color",
1256 reinterpret_cast<float*>(&bounds_color));
1257 ImGui::SliderFloat2("Translation", offset, 0,
1258 pass.GetRenderTargetSize().width);
1259 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1260 ImGui::SliderFloat2("Scale", scale, 0, 3);
1261 ImGui::SliderFloat2("Skew", skew, -3, 3);
1262 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1263 ImGui::SliderFloat("Effect transform scale", &effect_transform_scale, 0,
1264 3);
1265 }
1266 ImGui::End();
1267
1268 std::shared_ptr<Contents> input;
1269 Size input_size;
1270
1271 auto input_rect =
1272 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1273 auto texture = std::make_shared<TextureContents>();
1274 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1275 texture->SetDestinationRect(input_rect);
1276 texture->SetTexture(boston);
1277 texture->SetOpacity(input_color.alpha);
1278
1279 input = texture;
1280 input_size = input_rect.GetSize();
1281
1282 auto contents = FilterContents::MakeMorphology(
1283 FilterInput::Make(input), Radius{radius[0]}, Radius{radius[1]},
1284 morphology_types[selected_morphology_type]);
1285 contents->SetEffectTransform(Matrix::MakeScale(
1286 Vector2{effect_transform_scale, effect_transform_scale}));
1287
1288 auto ctm = Matrix::MakeScale(GetContentScale()) *
1289 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1290 Matrix::MakeRotationZ(Radians(rotation)) *
1291 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1292 Matrix::MakeSkew(skew[0], skew[1]) *
1293 Matrix::MakeTranslation(-Point(input_size) / 2);
1294
1295 Entity entity;
1296 entity.SetContents(contents);
1297 entity.SetTransform(ctm);
1298
1299 entity.Render(context, pass);
1300
1301 // Renders a red "cover" rectangle that shows the original position of the
1302 // unfiltered input.
1303 Entity cover_entity;
1304 cover_entity.SetContents(SolidColorContents::Make(
1305 PathBuilder{}.AddRect(input_rect).TakePath(), cover_color));
1306 cover_entity.SetTransform(ctm);
1307
1308 cover_entity.Render(context, pass);
1309
1310 // Renders a green bounding rect of the target filter.
1311 Entity bounds_entity;
1312 bounds_entity.SetContents(SolidColorContents::Make(
1313 PathBuilder{}.AddRect(contents->GetCoverage(entity).value()).TakePath(),
1314 bounds_color));
1315 bounds_entity.SetTransform(Matrix());
1316
1317 bounds_entity.Render(context, pass);
1318
1319 return true;
1320 };
1321 ASSERT_TRUE(OpenPlaygroundHere(callback));
1322 }

References impeller::PathBuilder::AddRect(), impeller::Color::alpha, impeller::Color::Black(), impeller::FilterContents::kDilate, impeller::FilterContents::kErode, impeller::kPi, impeller::SolidColorContents::Make(), impeller::FilterInput::Make(), 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() [330/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | PointFieldGeometryCoverage |
| ) |  |

Definition at line 2599 of file entity_unittests.cc.

2599 {
2600 std::vector<Point> points = {{10, 20}, {100, 200}};
2601 auto geometry = Geometry::MakePointField(points, 5.0, false);
2602 ASSERT_EQ(*geometry->GetCoverage(Matrix()), Rect::MakeLTRB(5, 15, 105, 205));
2603 ASSERT_EQ(*geometry->GetCoverage(Matrix::MakeTranslation({30, 0, 0})),
2604 Rect::MakeLTRB(35, 15, 135, 205));
2605 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakePointField(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [331/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | PointFieldGeometryDivisions |
| ) |  |

Definition at line 2581 of file entity_unittests.cc.

2581 {
2582 // Square always gives 4 divisions.
2583 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(24.0, false), 4u);
2584 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(2.0, false), 4u);
2585 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(200.0, false), 4u);
2586
2587 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(0.5, true), 4u);
2588 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(1.5, true), 8u);
2589 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(5.5, true), 24u);
2590 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(12.5, true), 34u);
2591 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(22.3, true), 22u);
2592 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(40.5, true), 40u);
2593 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(100.0, true), 100u);
2594 // Caps at 140.
2595 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(1000.0, true), 140u);
2596 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(20000.0, true), 140u);
2597 }

References impeller::PointFieldGeometry::ComputeCircleDivisions().

## ◆ TEST_P() [332/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RadialGradientContentsIsOpaque |
| ) |  |

Definition at line 2549 of file entity_unittests.cc.

2549 {
2550 RadialGradientContents contents;
2551 contents.SetColors({Color::CornflowerBlue()});
2552 ASSERT_TRUE(contents.IsOpaque());
2553 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2554 ASSERT_FALSE(contents.IsOpaque());
2555 contents.SetColors({Color::CornflowerBlue()});
2556 contents.SetTileMode(Entity::TileMode::kDecal);
2557 ASSERT_FALSE(contents.IsOpaque());
2558 }

References impeller::Color::CornflowerBlue(), impeller::RadialGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::RadialGradientContents::SetColors(), impeller::RadialGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [333/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RendersDstPerColorWithAlpha |
| ) |  |

Definition at line 44 of file vertices_contents_unittests.cc.

44 {
45 using FS = GeometryColorPipeline::FragmentShader;
46
47 auto contents = std::make_shared<VerticesContents>();
48 auto vertices = CreateColorVertices(
49 {{0, 0}, {100, 0}, {0, 100}, {100, 0}, {0, 100}, {100, 100}},
50 {Color::Red(), Color::Red(), Color::Red(), Color::Red(), Color::Red(),
51 Color::Red()});
52 auto src_contents = SolidColorContents::Make(
53 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath(),
54 Color::Red());
55
56 contents->SetGeometry(vertices);
57 contents->SetAlpha(0.5);
58 contents->SetBlendMode(BlendMode::kDestination);
59 contents->SetSourceContents(std::move(src_contents));
60
61 auto content_context = GetContentContext();
62 auto buffer = content_context->GetContext()->CreateCommandBuffer();
63 auto render_target =
64 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
65 *content_context->GetContext(), {100, 100},
66 /*mip_count=*/1);
67 auto render_pass = buffer->CreateRenderPass(render_target);
68 auto recording_pass = std::make_shared<RecordingRenderPass>(
69 render_pass, GetContext(), render_target);
70 Entity entity;
71
72 ASSERT_TRUE(recording_pass->GetCommands().empty());
73 ASSERT_TRUE(contents->Render(*content_context, entity, *recording_pass));
74
75 ASSERT_TRUE(recording_pass->GetCommands().size() > 0);
76 const auto& cmd = recording_pass->GetCommands()[0];
77 auto* frag_uniforms = GetFragInfo<FS>(cmd);
78
79 ASSERT_TRUE(frag_uniforms);
80 ASSERT_EQ(frag_uniforms->alpha, 0.5);
81
82 if (GetParam() == PlaygroundBackend::kMetal) {
83 recording_pass->EncodeCommands();
84 }
85 }

References impeller::PathBuilder::AddRect(), CreateColorVertices(), impeller::kDestination, impeller::kMetal, impeller::SolidColorContents::Make(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::Color::Red().

## ◆ TEST_P() [334/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RRectShadowTest |
| ) |  |

Definition at line 1786 of file entity_unittests.cc.

1786 {
1787 auto callback = [&](ContentContext& context, RenderPass& pass) {
1788 static Color color = Color::Red();
1789 static float corner_radius = 100;
1790 static float blur_radius = 100;
1791 static bool show_coverage = false;
1792 static Color coverage_color = Color::Green().WithAlpha(0.2);
1793
1794 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1795 ImGui::SliderFloat("Corner radius", &corner_radius, 0, 300);
1796 ImGui::SliderFloat("Blur radius", &blur_radius, 0, 300);
1797 ImGui::ColorEdit4("Color", reinterpret_cast<Scalar*>(&color));
1798 ImGui::Checkbox("Show coverage", &show_coverage);
1799 if (show_coverage) {
1800 ImGui::ColorEdit4("Coverage color",
1801 reinterpret_cast<Scalar*>(&coverage_color));
1802 }
1803 ImGui::End();
1804
1805 static PlaygroundPoint top_left_point(Point(200, 200), 30, Color::White());
1806 static PlaygroundPoint bottom_right_point(Point(600, 400), 30,
1807 Color::White());
1808 auto [top_left, bottom_right] =
1809 DrawPlaygroundLine(top_left_point, bottom_right_point);
1810 auto rect =
1811 Rect::MakeLTRB(top_left.x, top_left.y, bottom_right.x, bottom_right.y);
1812
1813 auto contents = std::make_unique<SolidRRectBlurContents>();
1814 contents->SetRRect(rect, {corner_radius, corner_radius});
1815 contents->SetColor(color);
1816 contents->SetSigma(Radius(blur_radius));
1817
1818 Entity entity;
1819 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
1820 entity.SetContents(std::move(contents));
1821 entity.Render(context, pass);
1822
1823 auto coverage = entity.GetCoverage();
1824 if (show_coverage && coverage.has_value()) {
1825 auto bounds_contents = std::make_unique<SolidColorContents>();
1826 bounds_contents->SetGeometry(Geometry::MakeFillPath(
1827 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath()));
1828 bounds_contents->SetColor(coverage_color.Premultiply());
1829 Entity bounds_entity;
1830 bounds_entity.SetContents(std::move(bounds_contents));
1831 bounds_entity.Render(context, pass);
1832 }
1833
1834 return true;
1835 };
1836 ASSERT_TRUE(OpenPlaygroundHere(callback));
1837 }

References impeller::PathBuilder::AddRect(), 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() [335/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffect |
| ) |  |

Definition at line 2194 of file entity_unittests.cc.

2194 {
2195 auto runtime_stages =
2196 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2197 auto runtime_stage =
2198 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2199 ASSERT_TRUE(runtime_stage);
2200 ASSERT_TRUE(runtime_stage->IsDirty());
2201
2202 bool expect_dirty = true;
2203 Pipeline<PipelineDescriptor>* first_pipeline;
2204 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2205 EXPECT_EQ(runtime_stage->IsDirty(), expect_dirty);
2206
2207 auto contents = std::make_shared<RuntimeEffectContents>();
2208 contents->SetGeometry(Geometry::MakeCover());
2209 contents->SetRuntimeStage(runtime_stage);
2210
2211 struct FragUniforms {
2212 Vector2 iResolution;
2213 Scalar iTime;
2214 } frag_uniforms = {
2215 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
2216 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
2217 };
2218 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2219 uniform_data->resize(sizeof(FragUniforms));
2220 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2221 contents->SetUniformData(uniform_data);
2222
2223 Entity entity;
2224 entity.SetContents(contents);
2225 bool result = contents->Render(context, entity, pass);
2226
2227 if (expect_dirty) {
2228 EXPECT_NE(first_pipeline, pass.GetCommands().back().pipeline.get());
2229 first_pipeline = pass.GetCommands().back().pipeline.get();
2230 } else {
2231 EXPECT_EQ(pass.GetCommands().back().pipeline.get(), first_pipeline);
2232 }
2233
2234 expect_dirty = false;
2235 return result;
2236 };
2237
2238 // Simulate some renders and hot reloading of the shader.
2239 auto content_context = GetContentContext();
2240 {
2241 RenderTarget target =
2242 content_context->GetRenderTargetCache()->CreateOffscreen(
2243 *content_context->GetContext(), {1, 1}, 1u);
2244
2245 testing::MockRenderPass mock_pass(GetContext(), target);
2246 callback(*content_context, mock_pass);
2247 callback(*content_context, mock_pass);
2248
2249 // Dirty the runtime stage.
2250 runtime_stages = OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2251 runtime_stage =
2252 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2253
2254 ASSERT_TRUE(runtime_stage->IsDirty());
2255 expect_dirty = true;
2256
2257 callback(*content_context, mock_pass);
2258 }
2259 }

References impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [336/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectCanSuccessfullyRender |
| ) |  |

Definition at line 2261 of file entity_unittests.cc.

2261 {
2262 auto runtime_stages =
2263 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2264 auto runtime_stage =
2265 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2266 ASSERT_TRUE(runtime_stage);
2267 ASSERT_TRUE(runtime_stage->IsDirty());
2268
2269 auto contents = std::make_shared<RuntimeEffectContents>();
2270 contents->SetGeometry(Geometry::MakeCover());
2271
2272 contents->SetRuntimeStage(runtime_stage);
2273
2274 struct FragUniforms {
2275 Vector2 iResolution;
2276 Scalar iTime;
2277 } frag_uniforms = {
2278 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
2279 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
2280 };
2281 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2282 uniform_data->resize(sizeof(FragUniforms));
2283 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2284 contents->SetUniformData(uniform_data);
2285
2286 Entity entity;
2287 entity.SetContents(contents);
2288
2289 // Create a render target with a depth-stencil, similar to how EntityPass
2290 // does.
2291 RenderTarget target =
2292 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
2293 *GetContext(), {GetWindowSize().width, GetWindowSize().height}, 1,
2294 "RuntimeEffect Texture");
2295 testing::MockRenderPass pass(GetContext(), target);
2296
2297 ASSERT_TRUE(contents->Render(*GetContentContext(), entity, pass));
2298 ASSERT_EQ(pass.GetCommands().size(), 1u);
2299 const auto& command = pass.GetCommands()[0];
2300 ASSERT_TRUE(command.pipeline->GetDescriptor()
2301 .GetDepthStencilAttachmentDescriptor()
2302 .has_value());
2303 ASSERT_TRUE(command.pipeline->GetDescriptor()
2304 .GetFrontStencilAttachmentDescriptor()
2305 .has_value());
2306 }

References impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [337/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectSetsRightSizeWhenUniformIsStruct |
| ) |  |

Definition at line 2308 of file entity_unittests.cc.

2308 {
2309 if (GetBackend() != PlaygroundBackend::kVulkan) {
2310 GTEST_SKIP() << "Test only applies to Vulkan";
2311 }
2312
2313 auto runtime_stages =
2314 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2315 auto runtime_stage =
2316 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2317 ASSERT_TRUE(runtime_stage);
2318 ASSERT_TRUE(runtime_stage->IsDirty());
2319
2320 auto contents = std::make_shared<RuntimeEffectContents>();
2321 contents->SetGeometry(Geometry::MakeCover());
2322 contents->SetRuntimeStage(runtime_stage);
2323
2324 struct FragUniforms {
2325 Vector2 iResolution;
2326 Scalar iTime;
2327 } frag_uniforms = {
2328 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
2329 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
2330 };
2331 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2332 uniform_data->resize(sizeof(FragUniforms));
2333 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2334 contents->SetUniformData(uniform_data);
2335
2336 Entity entity;
2337 entity.SetContents(contents);
2338
2339 auto context = GetContentContext();
2340 RenderTarget target = context->GetRenderTargetCache()->CreateOffscreen(
2341 *context->GetContext(), {1, 1}, 1u);
2342
2343 testing::MockRenderPass pass(GetContext(), target);
2344 ASSERT_TRUE(contents->Render(*context, entity, pass));
2345 ASSERT_EQ(pass.GetCommands().size(), 1u);
2346 const auto& command = pass.GetCommands()[0];
2347 ASSERT_EQ(command.fragment_bindings.buffers.size(), 1u);
2348 // 16 bytes:
2349 // 8 bytes for iResolution
2350 // 4 bytes for iTime
2351 // 4 bytes padding
2352 EXPECT_EQ(command.fragment_bindings.buffers[0].view.resource.range.length,
2353 16u);
2354 }

References impeller::kVulkan, impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [338/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SetBlendMode |
| ) |  |

Definition at line 1324 of file entity_unittests.cc.

1324 {
1325 Entity entity;
1326 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kSourceOver);
1327 entity.SetBlendMode(BlendMode::kClear);
1328 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kClear);
1329 }

References impeller::Entity::GetBlendMode(), impeller::kClear, impeller::kSourceOver, and impeller::Entity::SetBlendMode().

## ◆ TEST_P() [339/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsIsOpaque |
| ) |  |

Definition at line 2522 of file entity_unittests.cc.

2522 {
2523 SolidColorContents contents;
2524 contents.SetColor(Color::CornflowerBlue());
2525 ASSERT_TRUE(contents.IsOpaque());
2526 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.5));
2527 ASSERT_FALSE(contents.IsOpaque());
2528 }

References impeller::Color::CornflowerBlue(), impeller::SolidColorContents::IsOpaque(), and impeller::SolidColorContents::SetColor().

## ◆ TEST_P() [340/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetMiterLimit |
| ) |  |

Definition at line 841 of file entity_unittests.cc.

841 {
842 {
843 auto geometry = Geometry::MakeStrokePath(Path{});
844 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
845 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
846 }
847
848 {
849 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, /*miter_limit=*/8.0);
850 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
851 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 8);
852 }
853
854 {
855 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, /*miter_limit=*/-1.0);
856 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
857 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
858 }
859 }

References impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [341/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetStrokeCapsAndJoins |
| ) |  |

Definition at line 819 of file entity_unittests.cc.

819 {
820 {
821 auto geometry = Geometry::MakeStrokePath(Path{});
822 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
823 // Defaults.
824 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kButt);
825 ASSERT_EQ(path_geometry->GetStrokeJoin(), Join::kMiter);
826 }
827
828 {
829 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kSquare);
830 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
831 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kSquare);
832 }
833
834 {
835 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kRound);
836 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
837 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kRound);
838 }
839 }

References impeller::kButt, impeller::kMiter, impeller::kRound, impeller::kSquare, and impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [342/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidFillCoverageIsCorrect |
| ) |  |

Definition at line 1613 of file entity_unittests.cc.

1613 {
1614 // No transform
1615 {
1616 auto fill = std::make_shared<SolidColorContents>();
1617 fill->SetColor(Color::CornflowerBlue());
1618 auto expected = Rect::MakeLTRB(100, 110, 200, 220);
1619 fill->SetGeometry(
1620 Geometry::MakeFillPath(PathBuilder{}.AddRect(expected).TakePath()));
1621
1622 auto coverage = fill->GetCoverage({});
1623 ASSERT_TRUE(coverage.has_value());
1624 ASSERT_RECT_NEAR(coverage.value(), expected);
1625 }
1626
1627 // Entity transform
1628 {
1629 auto fill = std::make_shared<SolidColorContents>();
1630 fill->SetColor(Color::CornflowerBlue());
1631 fill->SetGeometry(Geometry::MakeFillPath(
1632 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath()));
1633
1634 Entity entity;
1635 entity.SetTransform(Matrix::MakeTranslation(Vector2(4, 5)));
1636 entity.SetContents(std::move(fill));
1637
1638 auto coverage = entity.GetCoverage();
1639 auto expected = Rect::MakeLTRB(104, 115, 204, 225);
1640 ASSERT_TRUE(coverage.has_value());
1641 ASSERT_RECT_NEAR(coverage.value(), expected);
1642 }
1643
1644 // No coverage for fully transparent colors
1645 {
1646 auto fill = std::make_shared<SolidColorContents>();
1647 fill->SetColor(Color::WhiteTransparent());
1648 fill->SetGeometry(Geometry::MakeFillPath(
1649 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath()));
1650
1651 auto coverage = fill->GetCoverage({});
1652 ASSERT_FALSE(coverage.has_value());
1653 }
1654 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidFillShouldRenderIsCorrect |
| ) |  |

Definition at line 1656 of file entity_unittests.cc.

1656 {
1657 // No path.
1658 {
1659 auto fill = std::make_shared<SolidColorContents>();
1660 fill->SetColor(Color::CornflowerBlue());
1661 ASSERT_FALSE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1662 ASSERT_FALSE(
1663 fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1664 }
1665
1666 // With path.
1667 {
1668 auto fill = std::make_shared<SolidColorContents>();
1669 fill->SetColor(Color::CornflowerBlue());
1670 fill->SetGeometry(Geometry::MakeFillPath(
1671 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1672 ASSERT_TRUE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1673 ASSERT_FALSE(
1674 fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1675 }
1676
1677 // With paint cover.
1678 {
1679 auto fill = std::make_shared<SolidColorContents>();
1680 fill->SetColor(Color::CornflowerBlue());
1681 fill->SetGeometry(Geometry::MakeCover());
1682 ASSERT_TRUE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1683 ASSERT_TRUE(
1684 fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1685 }
1686 }

References impeller::PathBuilder::AddRect(), impeller::Color::CornflowerBlue(), impeller::Geometry::MakeCover(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST_P() [344/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidStrokeCoverageIsCorrect |
| ) |  |

Definition at line 1337 of file entity_unittests.cc.

1337 {
1338 {
1339 auto geometry = Geometry::MakeStrokePath(
1340 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1341 Cap::kButt, Join::kBevel);
1342
1343 Entity entity;
1344 auto contents = std::make_unique<SolidColorContents>();
1345 contents->SetGeometry(std::move(geometry));
1346 contents->SetColor(Color::Black());
1347 entity.SetContents(std::move(contents));
1348 auto actual = entity.GetCoverage();
1349 auto expected = Rect::MakeLTRB(-2, -2, 12, 12);
1350 ASSERT_TRUE(actual.has_value());
1351 ASSERT_RECT_NEAR(actual.value(), expected);
1352 }
1353
1354 // Cover the Cap::kSquare case.
1355 {
1356 auto geometry = Geometry::MakeStrokePath(
1357 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1358 Cap::kSquare, Join::kBevel);
1359
1360 Entity entity;
1361 auto contents = std::make_unique<SolidColorContents>();
1362 contents->SetGeometry(std::move(geometry));
1363 contents->SetColor(Color::Black());
1364 entity.SetContents(std::move(contents));
1365 auto actual = entity.GetCoverage();
1366 auto expected =
1367 Rect::MakeLTRB(-sqrt(8), -sqrt(8), 10 + sqrt(8), 10 + sqrt(8));
1368 ASSERT_TRUE(actual.has_value());
1369 ASSERT_RECT_NEAR(actual.value(), expected);
1370 }
1371
1372 // Cover the Join::kMiter case.
1373 {
1374 auto geometry = Geometry::MakeStrokePath(
1375 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 2.0,
1376 Cap::kSquare, Join::kMiter);
1377
1378 Entity entity;
1379 auto contents = std::make_unique<SolidColorContents>();
1380 contents->SetGeometry(std::move(geometry));
1381 contents->SetColor(Color::Black());
1382 entity.SetContents(std::move(contents));
1383 auto actual = entity.GetCoverage();
1384 auto expected = Rect::MakeLTRB(-4, -4, 14, 14);
1385 ASSERT_TRUE(actual.has_value());
1386 ASSERT_RECT_NEAR(actual.value(), expected);
1387 }
1388 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SpecializationConstantsAreAppliedToVariants |
| ) |  |

Definition at line 2684 of file entity_unittests.cc.

2684 {
2685 auto content_context = GetContentContext();
2686
2687 auto default_color_burn = content_context->GetBlendColorBurnPipeline({
2688 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2689 .has_depth_stencil_attachments = false,
2690 });
2691 auto alt_color_burn = content_context->GetBlendColorBurnPipeline(
2692 {.color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2693 .has_depth_stencil_attachments = true});
2694
2695 ASSERT_NE(default_color_burn, alt_color_burn);
2696 ASSERT_EQ(default_color_burn->GetDescriptor().GetSpecializationConstants(),
2697 alt_color_burn->GetDescriptor().GetSpecializationConstants());
2698
2699 auto decal_supported = static_cast<Scalar>(
2700 GetContext()->GetCapabilities()->SupportsDecalSamplerAddressMode());
2701 std::vector<Scalar> expected_constants = {5, decal_supported};
2702 ASSERT_EQ(default_color_burn->GetDescriptor().GetSpecializationConstants(),
2703 expected_constants);
2704 }

References impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [346/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilter |
| ) |  |

Definition at line 1999 of file entity_unittests.cc.

1999 {
2000 auto image = CreateTextureForFixture("embarcadero.jpg");
2001 ASSERT_TRUE(image);
2002
2003 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2004 auto filtered =
2005 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(image));
2006
2007 // Define the entity that will serve as the control image as a Gaussian blur
2008 // filter with no filter at all.
2009 Entity entity_left;
2010 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
2011 Matrix::MakeTranslation({100, 300}) *
2012 Matrix::MakeScale(Vector2{0.5, 0.5}));
2013 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
2014 Sigma{0}, Sigma{0});
2015 entity_left.SetContents(unfiltered);
2016
2017 // Define the entity that will be filtered from sRGB to linear.
2018 Entity entity_right;
2019 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
2020 Matrix::MakeTranslation({500, 300}) *
2021 Matrix::MakeScale(Vector2{0.5, 0.5}));
2022 entity_right.SetContents(filtered);
2023 return entity_left.Render(context, pass) &&
2024 entity_right.Render(context, pass);
2025 };
2026
2027 ASSERT_TRUE(OpenPlaygroundHere(callback));
2028 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilterCoverageIsCorrect |
| ) |  |

Definition at line 1978 of file entity_unittests.cc.

1978 {
1979 // Set up a simple color background.
1980 auto fill = std::make_shared<SolidColorContents>();
1981 fill->SetGeometry(Geometry::MakeFillPath(
1982 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1983 fill->SetColor(Color::DeepPink());
1984
1985 auto filter =
1986 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(fill));
1987
1988 Entity e;
1989 e.SetTransform(Matrix());
1990
1991 // Confirm that the actual filter coverage matches the expected coverage.
1992 auto actual = filter->GetCoverage(e);
1993 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1994
1995 ASSERT_TRUE(actual.has_value());
1996 ASSERT_RECT_NEAR(actual.value(), expected);
1997 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeCapAndJoinTest |
| ) |  |

Definition at line 383 of file entity_unittests.cc.

383 {
384 const Point padding(300, 250);
385 const Point margin(140, 180);
386
387 auto callback = [&](ContentContext& context, RenderPass& pass) {
388 // Slightly above sqrt(2) by default, so that right angles are just below
389 // the limit and acute angles are over the limit (causing them to get
390 // beveled).
391 static Scalar miter_limit = 1.41421357;
392 static Scalar width = 30;
393
394 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
395 {
396 ImGui::SliderFloat("Miter limit", &miter_limit, 0, 30);
397 ImGui::SliderFloat("Stroke width", &width, 0, 100);
398 if (ImGui::Button("Reset")) {
399 miter_limit = 1.41421357;
400 width = 30;
401 }
402 }
403 ImGui::End();
404
405 auto world_matrix = Matrix::MakeScale(GetContentScale());
406 auto render_path = [width = width, &context, &pass, &world_matrix](
407 const Path& path, Cap cap, Join join) {
408 auto contents = std::make_unique<SolidColorContents>();
409 contents->SetGeometry(
410 Geometry::MakeStrokePath(path, width, miter_limit, cap, join));
411 contents->SetColor(Color::Red());
412
413 Entity entity;
414 entity.SetTransform(world_matrix);
415 entity.SetContents(std::move(contents));
416
417 auto coverage = entity.GetCoverage();
418 if (coverage.has_value()) {
419 auto bounds_contents = std::make_unique<SolidColorContents>();
420 bounds_contents->SetGeometry(Geometry::MakeFillPath(
421 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath()));
422 bounds_contents->SetColor(Color::Green().WithAlpha(0.5));
423 Entity bounds_entity;
424 bounds_entity.SetContents(std::move(bounds_contents));
425 bounds_entity.Render(context, pass);
426 }
427
428 entity.Render(context, pass);
429 };
430
431 const Point a_def(0, 0), b_def(0, 100), c_def(150, 0), d_def(150, -100),
432 e_def(75, 75);
433 const Scalar r = 30;
434 // Cap::kButt demo.
435 {
436 Point off = Point(0, 0) * padding + margin;
437 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
438 static PlaygroundPoint point_b(off + b_def, r, Color::White());
439 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
440 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
441 static PlaygroundPoint point_d(off + d_def, r, Color::White());
442 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
443 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
444 Cap::kButt, Join::kBevel);
445 }
446
447 // Cap::kSquare demo.
448 {
449 Point off = Point(1, 0) * padding + margin;
450 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
451 static PlaygroundPoint point_b(off + b_def, r, Color::White());
452 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
453 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
454 static PlaygroundPoint point_d(off + d_def, r, Color::White());
455 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
456 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
457 Cap::kSquare, Join::kBevel);
458 }
459
460 // Cap::kRound demo.
461 {
462 Point off = Point(2, 0) * padding + margin;
463 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
464 static PlaygroundPoint point_b(off + b_def, r, Color::White());
465 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
466 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
467 static PlaygroundPoint point_d(off + d_def, r, Color::White());
468 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
469 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
470 Cap::kRound, Join::kBevel);
471 }
472
473 // Join::kBevel demo.
474 {
475 Point off = Point(0, 1) * padding + margin;
476 static PlaygroundPoint point_a =
477 PlaygroundPoint(off + a_def, r, Color::White());
478 static PlaygroundPoint point_b =
479 PlaygroundPoint(off + e_def, r, Color::White());
480 static PlaygroundPoint point_c =
481 PlaygroundPoint(off + c_def, r, Color::White());
482 Point a = DrawPlaygroundPoint(point_a);
483 Point b = DrawPlaygroundPoint(point_b);
484 Point c = DrawPlaygroundPoint(point_c);
485 render_path(
486 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
487 Cap::kButt, Join::kBevel);
488 }
489
490 // Join::kMiter demo.
491 {
492 Point off = Point(1, 1) * padding + margin;
493 static PlaygroundPoint point_a(off + a_def, r, Color::White());
494 static PlaygroundPoint point_b(off + e_def, r, Color::White());
495 static PlaygroundPoint point_c(off + c_def, r, Color::White());
496 Point a = DrawPlaygroundPoint(point_a);
497 Point b = DrawPlaygroundPoint(point_b);
498 Point c = DrawPlaygroundPoint(point_c);
499 render_path(
500 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
501 Cap::kButt, Join::kMiter);
502 }
503
504 // Join::kRound demo.
505 {
506 Point off = Point(2, 1) * padding + margin;
507 static PlaygroundPoint point_a(off + a_def, r, Color::White());
508 static PlaygroundPoint point_b(off + e_def, r, Color::White());
509 static PlaygroundPoint point_c(off + c_def, r, Color::White());
510 Point a = DrawPlaygroundPoint(point_a);
511 Point b = DrawPlaygroundPoint(point_b);
512 Point c = DrawPlaygroundPoint(point_c);
513 render_path(
514 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
515 Cap::kButt, Join::kRound);
516 }
517
518 return true;
519 };
520 ASSERT_TRUE(OpenPlaygroundHere(callback));
521 }

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(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::PathBuilder::TakePath(), and impeller::Color::White().

## ◆ TEST_P() [349/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeWithTextureContents |
| ) |  |

Definition at line 319 of file entity_unittests.cc.

319 {
320 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
321 Path path = PathBuilder{}
322 .MoveTo({100, 100})
323 .LineTo({100, 200})
324 .MoveTo({100, 300})
325 .LineTo({100, 400})
326 .MoveTo({100, 500})
327 .LineTo({100, 600})
328 .TakePath();
329
330 Entity entity;
331 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
332 auto contents = std::make_unique<TiledTextureContents>();
333 contents->SetGeometry(Geometry::MakeStrokePath(path, 100.0));
334 contents->SetTexture(bridge);
335 contents->SetTileModes(Entity::TileMode::kClamp, Entity::TileMode::kClamp);
336 entity.SetContents(std::move(contents));
337 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
338 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SweepGradientContentsIsOpaque |
| ) |  |

Definition at line 2560 of file entity_unittests.cc.

2560 {
2561 RadialGradientContents contents;
2562 contents.SetColors({Color::CornflowerBlue()});
2563 ASSERT_TRUE(contents.IsOpaque());
2564 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2565 ASSERT_FALSE(contents.IsOpaque());
2566 contents.SetColors({Color::CornflowerBlue()});
2567 contents.SetTileMode(Entity::TileMode::kDecal);
2568 ASSERT_FALSE(contents.IsOpaque());
2569 }

References impeller::Color::CornflowerBlue(), impeller::RadialGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::RadialGradientContents::SetColors(), impeller::RadialGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [351/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TextContentsCeilsGlyphScaleToDecimal |
| ) |  |

Definition at line 2627 of file entity_unittests.cc.

2627 {
2628 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.4321111f, 12), 0.43f);
2629 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.5321111f, 12), 0.53f);
2630 ASSERT_EQ(TextFrame::RoundScaledFontSize(2.1f, 12), 2.1f);
2631 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.0f, 12), 0.0f);
2632 }

References impeller::TextFrame::RoundScaledFontSize().

## ◆ TEST_P() [352/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ThreeStrokesInOnePath |
| ) |  |

Definition at line 300 of file entity_unittests.cc.

300 {
301 Path path = PathBuilder{}
302 .MoveTo({100, 100})
303 .LineTo({100, 200})
304 .MoveTo({100, 300})
305 .LineTo({100, 400})
306 .MoveTo({100, 500})
307 .LineTo({100, 600})
308 .TakePath();
309
310 Entity entity;
311 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
312 auto contents = std::make_unique<SolidColorContents>();
313 contents->SetGeometry(Geometry::MakeStrokePath(path, 5.0));
314 contents->SetColor(Color::Red());
315 entity.SetContents(std::move(contents));
316 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
317 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsIsOpaque |
| ) |  |

Definition at line 2571 of file entity_unittests.cc.

2571 {
2572 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
2573 TiledTextureContents contents;
2574 contents.SetTexture(bay_bridge);
2575 // This is a placeholder test. Images currently never decompress as opaque
2576 // (whether in Flutter or the playground), and so this should currently always
2577 // return false in practice.
2578 ASSERT_FALSE(contents.IsOpaque());
2579 }

References impeller::TiledTextureContents::IsOpaque(), and impeller::TiledTextureContents::SetTexture().

## ◆ TEST_P() [354/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsRendersWithCorrectPipeline |
| ) |  |

Definition at line 20 of file tiled_texture_contents_unittests.cc.

20 {
21 TextureDescriptor texture_desc;
22 texture_desc.size = {100, 100};
23 texture_desc.type = TextureType::kTexture2D;
24 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
25 texture_desc.storage_mode = StorageMode::kDevicePrivate;
26 auto texture =
27 GetContext()->GetResourceAllocator()->CreateTexture(texture_desc);
28
29 TiledTextureContents contents;
30 contents.SetTexture(texture);
31 contents.SetGeometry(Geometry::MakeCover());
32
33 auto content_context = GetContentContext();
34 auto buffer = content_context->GetContext()->CreateCommandBuffer();
35 auto render_target =
36 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
37 *content_context->GetContext(), {100, 100},
38 /*mip_count=*/1);
39 auto render_pass = buffer->CreateRenderPass(render_target);
40 auto recording_pass = std::make_shared<RecordingRenderPass>(
41 render_pass, GetContext(), render_target);
42
43 ASSERT_TRUE(contents.Render(*GetContentContext(), {}, *recording_pass));
44 const std::vector<Command>& commands = recording_pass->GetCommands();
45
46 ASSERT_EQ(commands.size(), 1u);
47 EXPECT_TRUE(commands[0].pipeline->GetDescriptor().GetLabel().find(
48 "TextureFill Pipeline") != std::string::npos);
49
50 if (GetParam() == PlaygroundBackend::kMetal) {
51 recording_pass->EncodeCommands();
52 }
53 }

References impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kMetal, impeller::kR8G8B8A8UNormInt, impeller::kTexture2D, impeller::Geometry::MakeCover(), impeller::TiledTextureContents::Render(), impeller::ColorSourceContents::SetGeometry(), impeller::TiledTextureContents::SetTexture(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::type.

## ◆ TEST_P() [355/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsRendersWithCorrectPipelineExternalOES |
| ) |  |

Definition at line 57 of file tiled_texture_contents_unittests.cc.

57 {
58 if (GetParam() != PlaygroundBackend::kOpenGLES) {
59 GTEST_SKIP_(
60 "External OES textures are only valid for the OpenGLES backend.");
61 }
62
63 TextureDescriptor texture_desc;
64 texture_desc.size = {100, 100};
65 texture_desc.type = TextureType::kTextureExternalOES;
66 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
67 texture_desc.storage_mode = StorageMode::kDevicePrivate;
68 auto texture =
69 GetContext()->GetResourceAllocator()->CreateTexture(texture_desc);
70
71 TiledTextureContents contents;
72 contents.SetTexture(texture);
73 contents.SetGeometry(Geometry::MakeCover());
74
75 auto content_context = GetContentContext();
76 auto buffer = content_context->GetContext()->CreateCommandBuffer();
77 auto render_target =
78 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
79 *content_context->GetContext(), {100, 100},
80 /*mip_count=*/1);
81 auto render_pass = buffer->CreateRenderPass(render_target);
82
83 ASSERT_TRUE(contents.Render(*GetContentContext(), {}, *render_pass));
84 const std::vector<Command>& commands = render_pass->GetCommands();
85
86 ASSERT_EQ(commands.size(), 1u);
87 EXPECT_TRUE(commands[0].pipeline->GetDescriptor().GetLabel().find(
88 "TiledTextureFillExternal Pipeline") != std::string::npos);
89 }

References impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kOpenGLES, impeller::kR8G8B8A8UNormInt, impeller::kTextureExternalOES, impeller::Geometry::MakeCover(), impeller::TiledTextureContents::Render(), impeller::ColorSourceContents::SetGeometry(), impeller::TiledTextureContents::SetTexture(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::type.

## ◆ TEST_P() [356/419]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TriangleInsideASquare |
| ) |  |

Definition at line 340 of file entity_unittests.cc.

340 {
341 auto callback = [&](ContentContext& context, RenderPass& pass) {
342 Point offset(100, 100);
343
344 static PlaygroundPoint point_a(Point(10, 10) + offset, 20, Color::White());
345 Point a = DrawPlaygroundPoint(point_a);
346 static PlaygroundPoint point_b(Point(210, 10) + offset, 20, Color::White());
347 Point b = DrawPlaygroundPoint(point_b);
348 static PlaygroundPoint point_c(Point(210, 210) + offset, 20,
349 Color::White());
350 Point c = DrawPlaygroundPoint(point_c);
351 static PlaygroundPoint point_d(Point(10, 210) + offset, 20, Color::White());
352 Point d = DrawPlaygroundPoint(point_d);
353 static PlaygroundPoint point_e(Point(50, 50) + offset, 20, Color::White());
354 Point e = DrawPlaygroundPoint(point_e);
355 static PlaygroundPoint point_f(Point(100, 50) + offset, 20, Color::White());
356 Point f = DrawPlaygroundPoint(point_f);
357 static PlaygroundPoint point_g(Point(50, 150) + offset, 20, Color::White());
358 Point g = DrawPlaygroundPoint(point_g);
359 Path path = PathBuilder{}
360 .MoveTo(a)
361 .LineTo(b)
362 .LineTo(c)
363 .LineTo(d)
364 .Close()
365 .MoveTo(e)
366 .LineTo(f)
367 .LineTo(g)
368 .Close()
369 .TakePath();
370
371 Entity entity;
372 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
373 auto contents = std::make_unique<SolidColorContents>();
374 contents->SetGeometry(Geometry::MakeStrokePath(path, 20.0));
375 contents->SetColor(Color::Red());
376 entity.SetContents(std::move(contents));
377
378 return entity.Render(context, pass);
379 };
380 ASSERT_TRUE(OpenPlaygroundHere(callback));
381 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | YUVToRGBFilter |
| ) |  |

Definition at line 2161 of file entity_unittests.cc.

2161 {
2162 if (GetParam() == PlaygroundBackend::kOpenGLES) {
2163 // TODO(114588) : Support YUV to RGB filter on OpenGLES backend.
2164 GTEST_SKIP_("YUV to RGB filter is not supported on OpenGLES backend yet.");
2165 }
2166
2167 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2168 YUVColorSpace yuv_color_space_array[2]{YUVColorSpace::kBT601FullRange,
2169 YUVColorSpace::kBT601LimitedRange};
2170 for (int i = 0; i < 2; i++) {
2171 auto yuv_color_space = yuv_color_space_array[i];
2172 auto textures =
2173 CreateTestYUVTextures(GetContext().get(), yuv_color_space);
2174 auto filter_contents = FilterContents::MakeYUVToRGBFilter(
2175 textures[0], textures[1], yuv_color_space);
2176 Entity filter_entity;
2177 filter_entity.SetContents(filter_contents);
2178 auto snapshot = filter_contents->RenderToSnapshot(context, filter_entity);
2179
2180 Entity entity;
2181 auto contents = TextureContents::MakeRect(Rect::MakeLTRB(0, 0, 256, 256));
2182 contents->SetTexture(snapshot->texture);
2183 contents->SetSourceRect(Rect::MakeSize(snapshot->texture->GetSize()));
2184 entity.SetContents(contents);
2185 entity.SetTransform(
2186 Matrix::MakeTranslation({static_cast<Scalar>(100 + 400 * i), 300}));
2187 entity.Render(context, pass);
2188 }
2189 return true;
2190 };
2191 ASSERT_TRUE(OpenPlaygroundHere(callback));
2192 }

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(), impeller::Entity::SetTransform(), and textures.

## ◆ TEST_P() [358/419]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CalculateUVsSimple |
| ) |  |

Definition at line 309 of file gaussian_blur_filter_contents_unittests.cc.

309 {
310 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
311 auto filter_input = FilterInput::Make(texture);
312 Entity entity;
313 Quad uvs = GaussianBlurFilterContents::CalculateUVs(
314 filter_input, entity, Rect::MakeSize(ISize(100, 100)), ISize(100, 100));
315 std::optional<Rect> uvs_bounds = Rect::MakePointBounds(uvs);
316 EXPECT_TRUE(uvs_bounds.has_value());
317 if (uvs_bounds.has_value()) {
318 EXPECT_TRUE(RectNear(uvs_bounds.value(), Rect::MakeXYWH(0, 0, 1, 1)));
319 }
320 }

References impeller::GaussianBlurFilterContents::CalculateUVs(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakePointBounds(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), and RectNear().

## ◆ TEST_P() [359/419]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageWithEffectTransform |
| ) |  |

Definition at line 161 of file gaussian_blur_filter_contents_unittests.cc.

161 {
162 Matrix effect_transform = Matrix::MakeScale({2.0, 2.0, 1.0});
163 fml::StatusOr<Scalar> sigma_radius_1 =
164 CalculateSigmaForBlurRadius(1.0, effect_transform);
165 ASSERT_TRUE(sigma_radius_1.ok());
166 GaussianBlurFilterContents contents(
167 /*sigma_x=*/sigma_radius_1.value(),
168 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
169 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
170 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
171 FilterInput::Vector inputs = {FilterInput::Make(texture)};
172 Entity entity;
173 entity.SetTransform(Matrix::MakeTranslation({100, 100, 0}));
174 std::optional<Rect> coverage =
175 contents.GetFilterCoverage(inputs, entity, effect_transform);
176 EXPECT_TRUE(coverage.has_value());
177 if (coverage.has_value()) {
178 EXPECT_RECT_NEAR(coverage.value(),
179 Rect::MakeLTRB(100 - 1, 100 - 1, 200 + 1, 200 + 1));
180 }
181 }

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

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageWithTexture |
| ) |  |

Definition at line 140 of file gaussian_blur_filter_contents_unittests.cc.

140 {
141 fml::StatusOr<Scalar> sigma_radius_1 =
142 CalculateSigmaForBlurRadius(1.0, Matrix());
143 ASSERT_TRUE(sigma_radius_1.ok());
144 GaussianBlurFilterContents contents(
145 /*sigma_X=*/sigma_radius_1.value(),
146 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
147 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
148 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
149 FilterInput::Vector inputs = {FilterInput::Make(texture)};
150 Entity entity;
151 entity.SetTransform(Matrix::MakeTranslation({100, 100, 0}));
152 std::optional<Rect> coverage =
153 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
154
155 EXPECT_TRUE(coverage.has_value());
156 if (coverage.has_value()) {
157 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(99, 99, 201, 201));
158 }
159 }

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

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverage |
| ) |  |

Definition at line 213 of file gaussian_blur_filter_contents_unittests.cc.

213 {
214 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
215 fml::StatusOr<Scalar> sigma_radius_1 =
216 CalculateSigmaForBlurRadius(1.0, Matrix());
217 ASSERT_TRUE(sigma_radius_1.ok());
218 auto contents = std::make_unique<GaussianBlurFilterContents>(
219 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
220 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
221 contents->SetInputs({FilterInput::Make(texture)});
222 std::shared_ptr<ContentContext> renderer = GetContentContext();
223
224 Entity entity;
225 std::optional<Entity> result =
226 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
227 EXPECT_TRUE(result.has_value());
228 if (result.has_value()) {
229 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
230 std::optional<Rect> result_coverage = result.value().GetCoverage();
231 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
232 EXPECT_TRUE(result_coverage.has_value());
233 EXPECT_TRUE(contents_coverage.has_value());
234 if (result_coverage.has_value() && contents_coverage.has_value()) {
235 EXPECT_TRUE(RectNear(contents_coverage.value(),
236 Rect::MakeLTRB(-1, -1, 101, 101)));
237 EXPECT_TRUE(
238 RectNear(result_coverage.value(), Rect::MakeLTRB(-1, -1, 101, 101)));
239 }
240 }
241 }

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

## ◆ TEST_P() [362/419]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageRotated |
| ) |  |

Definition at line 276 of file gaussian_blur_filter_contents_unittests.cc.

277 {
278 std::shared_ptr<Texture> texture = MakeTexture(ISize(400, 300));
279 fml::StatusOr<Scalar> sigma_radius_1 =
280 CalculateSigmaForBlurRadius(1.0, Matrix());
281 auto contents = std::make_unique<GaussianBlurFilterContents>(
282 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
283 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
284 contents->SetInputs({FilterInput::Make(texture)});
285 std::shared_ptr<ContentContext> renderer = GetContentContext();
286
287 Entity entity;
288 // Rotate around the top left corner, then push it over to (100, 100).
289 entity.SetTransform(Matrix::MakeTranslation({400, 100, 0}) *
290 Matrix::MakeRotationZ(Degrees(90.0)));
291 std::optional<Entity> result =
292 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
293 EXPECT_TRUE(result.has_value());
294 if (result.has_value()) {
295 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
296 std::optional<Rect> result_coverage = result.value().GetCoverage();
297 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
298 EXPECT_TRUE(result_coverage.has_value());
299 EXPECT_TRUE(contents_coverage.has_value());
300 if (result_coverage.has_value() && contents_coverage.has_value()) {
301 EXPECT_TRUE(RectNear(contents_coverage.value(),
302 Rect::MakeLTRB(99, 99, 401, 501)));
303 EXPECT_TRUE(
304 RectNear(result_coverage.value(), Rect::MakeLTRB(99, 99, 401, 501)));
305 }
306 }
307 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeTranslation(), RectNear(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [363/419]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageTranslate |
| ) |  |

Definition at line 243 of file gaussian_blur_filter_contents_unittests.cc.

244 {
245 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
246 fml::StatusOr<Scalar> sigma_radius_1 =
247 CalculateSigmaForBlurRadius(1.0, Matrix());
248 ASSERT_TRUE(sigma_radius_1.ok());
249 auto contents = std::make_unique<GaussianBlurFilterContents>(
250 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
251 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
252 contents->SetInputs({FilterInput::Make(texture)});
253 std::shared_ptr<ContentContext> renderer = GetContentContext();
254
255 Entity entity;
256 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
257 std::optional<Entity> result =
258 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
259
260 EXPECT_TRUE(result.has_value());
261 if (result.has_value()) {
262 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
263 std::optional<Rect> result_coverage = result.value().GetCoverage();
264 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
265 EXPECT_TRUE(result_coverage.has_value());
266 EXPECT_TRUE(contents_coverage.has_value());
267 if (result_coverage.has_value() && contents_coverage.has_value()) {
268 EXPECT_TRUE(RectNear(contents_coverage.value(),
269 Rect::MakeLTRB(99, 199, 201, 301)));
270 EXPECT_TRUE(
271 RectNear(result_coverage.value(), Rect::MakeLTRB(99, 199, 201, 301)));
272 }
273 }
274 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), RectNear(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [364/419]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithDestinationRect |
| ) |  |

Definition at line 322 of file gaussian_blur_filter_contents_unittests.cc.

322 {
323 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
324 auto texture_contents = std::make_shared<TextureContents>();
325 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
326 texture_contents->SetTexture(texture);
327 texture_contents->SetDestinationRect(Rect::MakeXYWH(
328 50, 40, texture->GetSize().width, texture->GetSize().height));
329
330 fml::StatusOr<Scalar> sigma_radius_1 =
331 CalculateSigmaForBlurRadius(1.0, Matrix());
332 auto contents = std::make_unique<GaussianBlurFilterContents>(
333 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
334 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
335 contents->SetInputs({FilterInput::Make(texture_contents)});
336 std::shared_ptr<ContentContext> renderer = GetContentContext();
337
338 Entity entity;
339 std::optional<Entity> result =
340 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
341 EXPECT_TRUE(result.has_value());
342 if (result.has_value()) {
343 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
344 std::optional<Rect> result_coverage = result.value().GetCoverage();
345 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
346 EXPECT_TRUE(result_coverage.has_value());
347 EXPECT_TRUE(contents_coverage.has_value());
348 if (result_coverage.has_value() && contents_coverage.has_value()) {
349 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
350 EXPECT_TRUE(RectNear(result_coverage.value(),
351 Rect::MakeLTRB(49.f, 39.f, 151.f, 141.f)));
352 }
353 }
354 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), and RectNear().

## ◆ TEST_P() [365/419]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithDestinationRectScaled |
| ) |  |

Definition at line 356 of file gaussian_blur_filter_contents_unittests.cc.

357 {
358 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
359 auto texture_contents = std::make_shared<TextureContents>();
360 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
361 texture_contents->SetTexture(texture);
362 texture_contents->SetDestinationRect(Rect::MakeXYWH(
363 50, 40, texture->GetSize().width, texture->GetSize().height));
364
365 fml::StatusOr<Scalar> sigma_radius_1 =
366 CalculateSigmaForBlurRadius(1.0, Matrix());
367 auto contents = std::make_unique<GaussianBlurFilterContents>(
368 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
369 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
370 contents->SetInputs({FilterInput::Make(texture_contents)});
371 std::shared_ptr<ContentContext> renderer = GetContentContext();
372
373 Entity entity;
374 entity.SetTransform(Matrix::MakeScale({2.0, 2.0, 1.0}));
375 std::optional<Entity> result =
376 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
377 EXPECT_TRUE(result.has_value());
378 if (result.has_value()) {
379 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
380 std::optional<Rect> result_coverage = result.value().GetCoverage();
381 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
382 EXPECT_TRUE(result_coverage.has_value());
383 EXPECT_TRUE(contents_coverage.has_value());
384 if (result_coverage.has_value() && contents_coverage.has_value()) {
385 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
386 EXPECT_TRUE(RectNear(contents_coverage.value(),
387 Rect::MakeLTRB(98.f, 78.f, 302.f, 282.f)));
388 }
389 }
390 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), RectNear(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [366/419]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithEffectTransform |
| ) |  |

Definition at line 392 of file gaussian_blur_filter_contents_unittests.cc.

392 {
393 Matrix effect_transform = Matrix::MakeScale({2.0, 2.0, 1.0});
394 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
395 auto texture_contents = std::make_shared<TextureContents>();
396 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
397 texture_contents->SetTexture(texture);
398 texture_contents->SetDestinationRect(Rect::MakeXYWH(
399 50, 40, texture->GetSize().width, texture->GetSize().height));
400
401 fml::StatusOr<Scalar> sigma_radius_1 =
402 CalculateSigmaForBlurRadius(1.0, effect_transform);
403 ASSERT_TRUE(sigma_radius_1.ok());
404 auto contents = std::make_unique<GaussianBlurFilterContents>(
405 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
406 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
407 contents->SetInputs({FilterInput::Make(texture_contents)});
408 contents->SetEffectTransform(effect_transform);
409 std::shared_ptr<ContentContext> renderer = GetContentContext();
410
411 Entity entity;
412 std::optional<Entity> result =
413 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
414 EXPECT_TRUE(result.has_value());
415 if (result.has_value()) {
416 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
417 std::optional<Rect> result_coverage = result.value().GetCoverage();
418 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
419 EXPECT_TRUE(result_coverage.has_value());
420 EXPECT_TRUE(contents_coverage.has_value());
421 if (result_coverage.has_value() && contents_coverage.has_value()) {
422 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
423 EXPECT_TRUE(RectNear(contents_coverage.value(),
424 Rect::MakeXYWH(49.f, 39.f, 102.f, 102.f)));
425 }
426 }
427 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), and RectNear().

## ◆ TEST_P() [367/419]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | CanEmplace |
| ) |  |

Definition at line 15 of file host_buffer_unittests.cc.

15 {
16 struct Length2 {
17 uint8_t pad[2];
18 };
19 static_assert(sizeof(Length2) == 2u);
20
21 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
22
23 for (size_t i = 0; i < 12500; i++) {
24 auto view = buffer->Emplace(Length2{});
25 ASSERT_TRUE(view);
26 ASSERT_EQ(view.range, Range(i * sizeof(Length2), 2u));
27 }
28 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [368/419]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | CanEmplaceWithAlignment |
| ) |  |

Definition at line 30 of file host_buffer_unittests.cc.

30 {
31 struct Length2 {
32 uint8_t pad[2];
33 };
34 static_assert(sizeof(Length2) == 2);
35 struct alignas(16) Align16 {
36 uint8_t pad[2];
37 };
38 static_assert(alignof(Align16) == 16);
39 static_assert(sizeof(Align16) == 16);
40
41 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
42 ASSERT_TRUE(buffer);
43
44 {
45 auto view = buffer->Emplace(Length2{});
46 ASSERT_TRUE(view);
47 ASSERT_EQ(view.range, Range(0u, 2u));
48 }
49
50 {
51 auto view = buffer->Emplace(Align16{});
52 ASSERT_TRUE(view);
53 ASSERT_EQ(view.range.offset, 16u);
54 ASSERT_EQ(view.range.length, 16u);
55 }
56 {
57 auto view = buffer->Emplace(Length2{});
58 ASSERT_TRUE(view);
59 ASSERT_EQ(view.range, Range(32u, 2u));
60 }
61
62 {
63 auto view = buffer->Emplace(Align16{});
64 ASSERT_TRUE(view);
65 ASSERT_EQ(view.range.offset, 48u);
66 ASSERT_EQ(view.range.length, 16u);
67 }
68 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [369/419]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplaceWithProcIsAligned |
| ) |  |

Definition at line 149 of file host_buffer_unittests.cc.

149 {
150 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
151
152 BufferView view = buffer->Emplace(std::array<char, 21>());
153 EXPECT_EQ(view.range, Range(0, 21));
154
155 view = buffer->Emplace(64, 16, [](uint8_t*) {});
156 EXPECT_EQ(view.range, Range(32, 64));
157 }

References impeller::HostBuffer::Create(), and impeller::BufferView::range.

## ◆ TEST_P() [370/419]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplacingLargerThanBlockSizeCreatesOneOffBuffer |
| ) |  |

Definition at line 106 of file host_buffer_unittests.cc.

106 {
107 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
108
109 // Emplace an amount larger than the block size, to verify that the host
110 // buffer does not create a buffer.
111 auto buffer_view = buffer->Emplace(nullptr, 1024000 + 10, 0);
112
113 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
114 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
115 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
116 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [371/419]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplacingLargerThanBlockSizeCreatesOneOffBufferCallback |
| ) |  |

Definition at line 93 of file host_buffer_unittests.cc.

94 {
95 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
96
97 // Emplace an amount larger than the block size, to verify that the host
98 // buffer does not create a buffer.
99 auto buffer_view = buffer->Emplace(1024000 + 10, 0, [](uint8_t* data) {});
100
101 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
102 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
103 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
104 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [372/419]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | HostBufferInitialState |
| ) |  |

Definition at line 70 of file host_buffer_unittests.cc.

70 {
71 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
72
73 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
74 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
75 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
76 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [373/419]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | ResetIncrementsFrameCounter |
| ) |  |

Definition at line 78 of file host_buffer_unittests.cc.

78 {
79 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
80
81 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
82
83 buffer->Reset();
84 EXPECT_EQ(buffer->GetStateForTest().current_frame, 1u);
85
86 buffer->Reset();
87 EXPECT_EQ(buffer->GetStateForTest().current_frame, 2u);
88
89 buffer->Reset();
90 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
91 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [374/419]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | UnusedBuffersAreDiscardedWhenResetting |
| ) |  |

Definition at line 118 of file host_buffer_unittests.cc.

118 {
119 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
120
121 // Emplace two large allocations to force the allocation of a second buffer.
122 auto buffer_view_a = buffer->Emplace(1020000, 0, [](uint8_t* data) {});
123 auto buffer_view_b = buffer->Emplace(1020000, 0, [](uint8_t* data) {});
124
125 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 1u);
126 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u);
127 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
128
129 // Reset until we get back to this frame.
130 for (auto i = 0; i < 3; i++) {
131 buffer->Reset();
132 }
133
134 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
135 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u);
136 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
137
138 // Now when we reset, the buffer should get dropped.
139 // Reset until we get back to this frame.
140 for (auto i = 0; i < 3; i++) {
141 buffer->Reset();
142 }
143
144 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
145 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
146 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
147 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [375/419]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanInstantiateFlutterGPUContext |
| ) |  |

Definition at line 103 of file renderer_dart_unittests.cc.

103 {
104 auto isolate = GetIsolate();
105 bool result = isolate->RunInIsolateScope([]() -> bool {
106 if (tonic::CheckAndHandleError(::Dart_Invoke(
107 Dart_RootLibrary(), tonic::ToDart("instantiateDefaultContext"), 0,
108 nullptr))) {
109 return false;
110 }
111 return true;
112 });
113
114 ASSERT_TRUE(result);
115 }

## ◆ TEST_P() [376/419]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanRunDartInPlaygroundFrame |
| ) |  |

Definition at line 83 of file renderer_dart_unittests.cc.

83 {
84 auto isolate = GetIsolate();
85
86 SinglePassCallback callback = [&](RenderPass& pass) {
87 ImGui::Begin("Dart test", nullptr);
88 ImGui::Text(
89 "This test executes Dart code during the playground frame callback.");
90 ImGui::End();
91
92 return isolate->RunInIsolateScope([]() -> bool {
93 if (tonic::CheckAndHandleError(::Dart_Invoke(
94 Dart_RootLibrary(), tonic::ToDart("sayHi"), 0, nullptr))) {
95 return false;
96 }
97 return true;
98 });
99 };
100 OpenPlaygroundHere(callback);
101 }

## ◆ TEST_P() [377/419]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | ArrayUniforms |
| ) |  |

Definition at line 887 of file renderer_unittests.cc.

887 {
888 using VS = ArrayVertexShader;
889 using FS = ArrayFragmentShader;
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 host_buffer = HostBuffer::Create(context->GetResourceAllocator());
902 SinglePassCallback callback = [&](RenderPass& pass) {
903 auto size = pass.GetRenderTargetSize();
904
905 pass.SetPipeline(pipeline);
906 pass.SetCommandLabel("Google Dots");
907 VertexBufferBuilder<VS::PerVertexData> builder;
908 builder.AddVertices({{Point()},
909 {Point(0, size.height)},
910 {Point(size.width, 0)},
911 {Point(size.width, 0)},
912 {Point(0, size.height)},
913 {Point(size.width, size.height)}});
914 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
915
916 VS::FrameInfo frame_info;
917 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
918 frame_info.mvp =
919 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
920 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
921
922 auto time = GetSecondsElapsed();
923 auto y_pos = [&time](float x) {
924 return 400 + 10 * std::cos(time * 5 + x / 6);
925 };
926
927 FS::FragInfo fs_uniform = {
928 .circle_positions = {Point(430, y_pos(0)), Point(480, y_pos(1)),
929 Point(530, y_pos(2)), Point(580, y_pos(3))},
930 .colors = {Color::MakeRGBA8(66, 133, 244, 255),
931 Color::MakeRGBA8(219, 68, 55, 255),
932 Color::MakeRGBA8(244, 180, 0, 255),
933 Color::MakeRGBA8(15, 157, 88, 255)},
934 };
935 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
936
937 pass.Draw();
938 host_buffer->Reset();
939 return true;
940 };
941 OpenPlaygroundHere(callback);
942 }

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

## ◆ TEST_P() [378/419]

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 auto render_target =
25 allocator->CreateOffscreenMSAA(*GetContext(), {100, 100}, 1);
26 auto resolve_texture =
27 render_target.GetColorAttachments().find(0u)->second.resolve_texture;
28 auto& 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 GetContext()->GetCommandQueue()->Submit({buffer});
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(), and impeller::kVulkan.

## ◆ TEST_P() [379/419]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToBuffer |
| ) |  |

Definition at line 570 of file renderer_unittests.cc.

570 {
571 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
572 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
573 }
574 auto context = GetContext();
575 ASSERT_TRUE(context);
576
577 using VS = MipmapsVertexShader;
578 using FS = MipmapsFragmentShader;
579 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
580 ASSERT_TRUE(desc.has_value());
581 desc->SetSampleCount(SampleCount::kCount4);
582 desc->SetStencilAttachmentDescriptors(std::nullopt);
583 auto mipmaps_pipeline =
584 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
585 ASSERT_TRUE(mipmaps_pipeline);
586
587 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
588 auto boston = CreateTextureForFixture("boston.jpg");
589 ASSERT_TRUE(bridge && boston);
590 const std::unique_ptr<const Sampler>& sampler =
591 context->GetSamplerLibrary()->GetSampler({});
592 ASSERT_TRUE(sampler);
593
594 TextureDescriptor texture_desc;
595 texture_desc.storage_mode = StorageMode::kHostVisible;
596 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
597 texture_desc.size = bridge->GetTextureDescriptor().size;
598 texture_desc.mip_count = 1u;
599 texture_desc.usage = TextureUsage::kRenderTarget |
600 TextureUsage::kShaderWrite | TextureUsage::kShaderRead;
601 DeviceBufferDescriptor device_buffer_desc;
602 device_buffer_desc.storage_mode = StorageMode::kHostVisible;
603 device_buffer_desc.size =
604 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
605 auto device_buffer =
606 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
607
608 // Vertex buffer.
609 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
610 vertex_builder.SetLabel("Box");
611 auto size = Point(boston->GetSize());
612 vertex_builder.AddVertices({
613 {{0, 0}, {0.0, 0.0}}, // 1
614 {{size.x, 0}, {1.0, 0.0}}, // 2
615 {{size.x, size.y}, {1.0, 1.0}}, // 3
616 {{0, 0}, {0.0, 0.0}}, // 1
617 {{size.x, size.y}, {1.0, 1.0}}, // 3
618 {{0, size.y}, {0.0, 1.0}}, // 4
619 });
620 auto vertex_buffer =
621 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
622 ASSERT_TRUE(vertex_buffer);
623
624 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
625 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
626 {
627 auto buffer = context->CreateCommandBuffer();
628 if (!buffer) {
629 return false;
630 }
631 buffer->SetLabel("Playground Command Buffer");
632 auto pass = buffer->CreateBlitPass();
633 if (!pass) {
634 return false;
635 }
636 pass->SetLabel("Playground Blit Pass");
637
638 if (render_target.GetColorAttachments().empty()) {
639 return false;
640 }
641
642 // Blit `bridge` to the top left corner of the texture.
643 pass->AddCopy(bridge, device_buffer);
644 pass->EncodeCommands(context->GetResourceAllocator());
645
646 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
647 return false;
648 }
649 }
650
651 {
652 auto buffer = context->CreateCommandBuffer();
653 if (!buffer) {
654 return false;
655 }
656 buffer->SetLabel("Playground Command Buffer");
657
658 auto pass = buffer->CreateRenderPass(render_target);
659 if (!pass) {
660 return false;
661 }
662 pass->SetLabel("Playground Render Pass");
663 {
664 pass->SetCommandLabel("Image");
665 pass->SetPipeline(mipmaps_pipeline);
666 pass->SetVertexBuffer(vertex_buffer);
667
668 VS::FrameInfo frame_info;
669 EXPECT_EQ(pass->GetOrthographicTransform(),
670 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
671 frame_info.mvp = pass->GetOrthographicTransform() *
672 Matrix::MakeScale(GetContentScale());
673 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
674
675 FS::FragInfo frag_info;
676 frag_info.lod = 0;
677 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
678
679 const std::unique_ptr<const Sampler>& sampler =
680 context->GetSamplerLibrary()->GetSampler({});
681 auto buffer_view = DeviceBuffer::AsBufferView(device_buffer);
682 auto texture =
683 context->GetResourceAllocator()->CreateTexture(texture_desc);
684 if (!texture->SetContents(device_buffer->OnGetContents(),
685 buffer_view.range.length)) {
686 VALIDATION_LOG << "Could not upload texture to device memory";
687 return false;
688 }
689 FS::BindTex(*pass, texture, sampler);
690
691 pass->Draw().ok();
692 }
693 pass->EncodeCommands();
694 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
695 return false;
696 }
697 }
698 host_buffer->Reset();
699 return true;
700 };
701 OpenPlaygroundHere(callback);
702 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::DeviceBuffer::AsBufferView(), 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() [380/419]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToTexture |
| ) |  |

Definition at line 455 of file renderer_unittests.cc.

455 {
456 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
457 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
458 }
459 auto context = GetContext();
460 ASSERT_TRUE(context);
461
462 using VS = MipmapsVertexShader;
463 using FS = MipmapsFragmentShader;
464 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
465 ASSERT_TRUE(desc.has_value());
466 desc->SetSampleCount(SampleCount::kCount4);
467 desc->SetStencilAttachmentDescriptors(std::nullopt);
468 auto mipmaps_pipeline =
469 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
470 ASSERT_TRUE(mipmaps_pipeline);
471
472 TextureDescriptor texture_desc;
473 texture_desc.storage_mode = StorageMode::kHostVisible;
474 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
475 texture_desc.size = {800, 600};
476 texture_desc.mip_count = 1u;
477 texture_desc.usage = TextureUsage::kRenderTarget | TextureUsage::kShaderRead;
478 auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
479 ASSERT_TRUE(texture);
480
481 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
482 auto boston = CreateTextureForFixture("boston.jpg");
483 ASSERT_TRUE(bridge && boston);
484 const std::unique_ptr<const Sampler>& sampler =
485 context->GetSamplerLibrary()->GetSampler({});
486 ASSERT_TRUE(sampler);
487
488 // Vertex buffer.
489 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
490 vertex_builder.SetLabel("Box");
491 auto size = Point(boston->GetSize());
492 vertex_builder.AddVertices({
493 {{0, 0}, {0.0, 0.0}}, // 1
494 {{size.x, 0}, {1.0, 0.0}}, // 2
495 {{size.x, size.y}, {1.0, 1.0}}, // 3
496 {{0, 0}, {0.0, 0.0}}, // 1
497 {{size.x, size.y}, {1.0, 1.0}}, // 3
498 {{0, size.y}, {0.0, 1.0}}, // 4
499 });
500 auto vertex_buffer =
501 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
502 ASSERT_TRUE(vertex_buffer);
503
504 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
505 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
506 auto buffer = context->CreateCommandBuffer();
507 if (!buffer) {
508 return false;
509 }
510 buffer->SetLabel("Playground Command Buffer");
511
512 {
513 auto pass = buffer->CreateBlitPass();
514 if (!pass) {
515 return false;
516 }
517 pass->SetLabel("Playground Blit Pass");
518
519 if (render_target.GetColorAttachments().empty()) {
520 return false;
521 }
522
523 // Blit `bridge` to the top left corner of the texture.
524 pass->AddCopy(bridge, texture);
525
526 if (!pass->EncodeCommands(context->GetResourceAllocator())) {
527 return false;
528 }
529 }
530
531 {
532 auto pass = buffer->CreateRenderPass(render_target);
533 if (!pass) {
534 return false;
535 }
536 pass->SetLabel("Playground Render Pass");
537 {
538 pass->SetCommandLabel("Image");
539 pass->SetPipeline(mipmaps_pipeline);
540 pass->SetVertexBuffer(vertex_buffer);
541
542 VS::FrameInfo frame_info;
543 EXPECT_EQ(pass->GetOrthographicTransform(),
544 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
545 frame_info.mvp = pass->GetOrthographicTransform() *
546 Matrix::MakeScale(GetContentScale());
547 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
548
549 FS::FragInfo frag_info;
550 frag_info.lod = 0;
551 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
552
553 auto& sampler = context->GetSamplerLibrary()->GetSampler({});
554 FS::BindTex(*pass, texture, sampler);
555
556 pass->Draw();
557 }
558 pass->EncodeCommands();
559 }
560
561 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
562 return false;
563 }
564 host_buffer->Reset();
565 return true;
566 };
567 OpenPlaygroundHere(callback);
568 }

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

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 const std::unique_ptr<const Sampler>& sampler =
79 context->GetSamplerLibrary()->GetSampler({});
80 ASSERT_TRUE(sampler);
81
82 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
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() [382/419]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanCreateCPUBackedTexture |
| ) |  |

Definition at line 991 of file renderer_unittests.cc.

991 {
992 if (GetParam() == PlaygroundBackend::kOpenGLES) {
993 GTEST_SKIP_("CPU backed textures are not supported on OpenGLES.");
994 }
995
996 auto context = GetContext();
997 auto allocator = context->GetResourceAllocator();
998 size_t dimension = 2;
999
1000 do {
1001 ISize size(dimension, dimension);
1002 TextureDescriptor texture_descriptor;
1003 texture_descriptor.storage_mode = StorageMode::kHostVisible;
1004 texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
1005 texture_descriptor.size = size;
1006 auto row_bytes =
1007 std::max(static_cast<uint16_t>(size.width * 4),
1008 allocator->MinimumBytesPerRow(texture_descriptor.format));
1009 auto buffer_size = size.height * row_bytes;
1010
1011 DeviceBufferDescriptor buffer_descriptor;
1012 buffer_descriptor.storage_mode = StorageMode::kHostVisible;
1013 buffer_descriptor.size = buffer_size;
1014
1015 auto buffer = allocator->CreateBuffer(buffer_descriptor);
1016
1017 ASSERT_TRUE(buffer);
1018
1019 auto texture = buffer->AsTexture(*allocator, texture_descriptor, row_bytes);
1020
1021 ASSERT_TRUE(texture);
1022 ASSERT_TRUE(texture->IsValid());
1023
1024 dimension *= 2;
1025 } while (dimension <= 8192);
1026 }

References impeller::TextureDescriptor::format, impeller::TSize< T >::height, impeller::kHostVisible, impeller::kOpenGLES, impeller::kR8G8B8A8UNormInt, impeller::DeviceBufferDescriptor::size, impeller::TextureDescriptor::size, impeller::DeviceBufferDescriptor::storage_mode, impeller::TextureDescriptor::storage_mode, and impeller::TSize< T >::width.

## ◆ TEST_P() [383/419]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanGenerateMipmaps |
| ) |  |

Definition at line 704 of file renderer_unittests.cc.

704 {
705 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
706 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
707 }
708 auto context = GetContext();
709 ASSERT_TRUE(context);
710
711 using VS = MipmapsVertexShader;
712 using FS = MipmapsFragmentShader;
713 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
714 ASSERT_TRUE(desc.has_value());
715 desc->SetSampleCount(SampleCount::kCount4);
716 desc->SetStencilAttachmentDescriptors(std::nullopt);
717 auto mipmaps_pipeline =
718 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
719 ASSERT_TRUE(mipmaps_pipeline);
720
721 auto boston = CreateTextureForFixture("boston.jpg", true);
722 ASSERT_TRUE(boston);
723
724 // Vertex buffer.
725 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
726 vertex_builder.SetLabel("Box");
727 auto size = Point(boston->GetSize());
728 vertex_builder.AddVertices({
729 {{0, 0}, {0.0, 0.0}}, // 1
730 {{size.x, 0}, {1.0, 0.0}}, // 2
731 {{size.x, size.y}, {1.0, 1.0}}, // 3
732 {{0, 0}, {0.0, 0.0}}, // 1
733 {{size.x, size.y}, {1.0, 1.0}}, // 3
734 {{0, size.y}, {0.0, 1.0}}, // 4
735 });
736 auto vertex_buffer =
737 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
738 ASSERT_TRUE(vertex_buffer);
739
740 bool first_frame = true;
741 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
742 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
743 const char* mip_filter_names[] = {"Nearest", "Linear"};
744 const MipFilter mip_filters[] = {MipFilter::kNearest, MipFilter::kLinear};
745 const char* min_filter_names[] = {"Nearest", "Linear"};
746 const MinMagFilter min_filters[] = {MinMagFilter::kNearest,
747 MinMagFilter::kLinear};
748
749 // UI state.
750 static int selected_mip_filter = 1;
751 static int selected_min_filter = 0;
752 static float lod = 4.5;
753
754 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
755 ImGui::Combo("Mip filter", &selected_mip_filter, mip_filter_names,
756 sizeof(mip_filter_names) / sizeof(char*));
757 ImGui::Combo("Min filter", &selected_min_filter, min_filter_names,
758 sizeof(min_filter_names) / sizeof(char*));
759 ImGui::SliderFloat("LOD", &lod, 0, boston->GetMipCount() - 1);
760 ImGui::End();
761
762 auto buffer = context->CreateCommandBuffer();
763 if (!buffer) {
764 return false;
765 }
766 buffer->SetLabel("Playground Command Buffer");
767
768 if (first_frame) {
769 auto pass = buffer->CreateBlitPass();
770 if (!pass) {
771 return false;
772 }
773 pass->SetLabel("Playground Blit Pass");
774
775 pass->GenerateMipmap(boston, "Boston Mipmap");
776
777 pass->EncodeCommands(context->GetResourceAllocator());
778 }
779
780 first_frame = false;
781
782 {
783 auto pass = buffer->CreateRenderPass(render_target);
784 if (!pass) {
785 return false;
786 }
787 pass->SetLabel("Playground Render Pass");
788 {
789 pass->SetCommandLabel("Image LOD");
790 pass->SetPipeline(mipmaps_pipeline);
791 pass->SetVertexBuffer(vertex_buffer);
792
793 VS::FrameInfo frame_info;
794 EXPECT_EQ(pass->GetOrthographicTransform(),
795 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
796 frame_info.mvp = pass->GetOrthographicTransform() *
797 Matrix::MakeScale(GetContentScale());
798 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
799
800 FS::FragInfo frag_info;
801 frag_info.lod = lod;
802 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
803
804 SamplerDescriptor sampler_desc;
805 sampler_desc.mip_filter = mip_filters[selected_mip_filter];
806 sampler_desc.min_filter = min_filters[selected_min_filter];
807 const std::unique_ptr<const Sampler>& sampler =
808 context->GetSamplerLibrary()->GetSampler(sampler_desc);
809 FS::BindTex(*pass, boston, sampler);
810
811 pass->Draw();
812 }
813 pass->EncodeCommands();
814 }
815
816 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
817 return false;
818 }
819 host_buffer->Reset();
820 return true;
821 };
822 OpenPlaygroundHere(callback);
823 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), 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() [384/419]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanLookupRenderTargetProperties |
| ) |  |

Definition at line 1268 of file renderer_unittests.cc.

1268 {
1269 auto context = GetContext();
1270 auto cmd_buffer = context->CreateCommandBuffer();
1271 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1272 GetContext()->GetResourceAllocator());
1273
1274 auto render_target = render_target_cache->CreateOffscreen(
1275 *context, {100, 100}, /*mip_count=*/1);
1276 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1277
1278 EXPECT_EQ(render_pass->GetSampleCount(), render_target.GetSampleCount());
1279 EXPECT_EQ(render_pass->GetRenderTargetPixelFormat(),
1280 render_target.GetRenderTargetPixelFormat());
1281 EXPECT_EQ(render_pass->HasStencilAttachment(),
1282 render_target.GetStencilAttachment().has_value());
1283 EXPECT_EQ(render_pass->GetRenderTargetSize(),
1284 render_target.GetRenderTargetSize());
1285 render_pass->EncodeCommands();
1286 }

## ◆ TEST_P() [385/419]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderInstanced |
| ) |  |

Definition at line 387 of file renderer_unittests.cc.

387 {
388 if (GetParam() == PlaygroundBackend::kOpenGLES) {
389 GTEST_SKIP_("Instancing is not supported on OpenGL.");
390 }
391 using VS = InstancedDrawVertexShader;
392 using FS = InstancedDrawFragmentShader;
393
394 VertexBufferBuilder<VS::PerVertexData> builder;
395
396 ASSERT_EQ(Tessellator::Result::kSuccess,
397 Tessellator{}.Tessellate(
398 PathBuilder{}
399 .AddRect(Rect::MakeXYWH(10, 10, 100, 100))
400 .TakePath(FillType::kOdd),
401 1.0f,
402 [&builder](const float* vertices, size_t vertices_count,
403 const uint16_t* indices, size_t indices_count) {
404 for (auto i = 0u; i < vertices_count * 2; i += 2) {
405 VS::PerVertexData data;
406 data.vtx = {vertices[i], vertices[i + 1]};
407 builder.AppendVertex(data);
408 }
409 for (auto i = 0u; i < indices_count; i++) {
410 builder.AppendIndex(indices[i]);
411 }
412 return true;
413 }));
414
415 ASSERT_NE(GetContext(), nullptr);
416 auto pipeline =
417 GetContext()
418 ->GetPipelineLibrary()
419 ->GetPipeline(PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(
420 *GetContext())
421 ->SetSampleCount(SampleCount::kCount4)
422 .SetStencilAttachmentDescriptors(std::nullopt))
423
424 .Get();
425 ASSERT_TRUE(pipeline && pipeline->IsValid());
426
427 static constexpr size_t kInstancesCount = 5u;
428 VS::InstanceInfo<kInstancesCount> instances;
429 for (size_t i = 0; i < kInstancesCount; i++) {
430 instances.colors[i] = Color::Random();
431 }
432
433 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
434 ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool {
435 pass.SetPipeline(pipeline);
436 pass.SetCommandLabel("InstancedDraw");
437
438 VS::FrameInfo frame_info;
439 EXPECT_EQ(pass.GetOrthographicTransform(),
440 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
441 frame_info.mvp =
442 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
443 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
444 VS::BindInstanceInfo(pass, host_buffer->EmplaceStorageBuffer(instances));
445 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
446
447 pass.SetInstanceCount(kInstancesCount);
448 pass.Draw();
449
450 host_buffer->Reset();
451 return true;
452 }));
453 }

References impeller::PathBuilder::AddRect(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendIndex(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendVertex(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::RenderPass::Draw(), impeller::RenderPass::GetOrthographicTransform(), impeller::RenderPass::GetRenderTargetSize(), impeller::kCount4, impeller::kOdd, impeller::kOpenGLES, impeller::Tessellator::kSuccess, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Random(), impeller::RenderPass::SetCommandLabel(), impeller::RenderPass::SetInstanceCount(), impeller::RenderPass::SetPipeline(), impeller::RenderPass::SetVertexBuffer(), and impeller::Tessellator::Tessellate().

## ◆ TEST_P() [386/419]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderMultiplePrimitives |
| ) |  |

Definition at line 211 of file renderer_unittests.cc.

211 {
212 using VS = BoxFadeVertexShader;
213 using FS = BoxFadeFragmentShader;
214 auto context = GetContext();
215 ASSERT_TRUE(context);
216 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
217 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
218 ASSERT_TRUE(desc.has_value());
219 desc->SetSampleCount(SampleCount::kCount4);
220 desc->SetStencilAttachmentDescriptors(std::nullopt);
221 auto box_pipeline =
222 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
223 ASSERT_TRUE(box_pipeline);
224
225 // Vertex buffer.
226 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
227 vertex_builder.SetLabel("Box");
228 vertex_builder.AddVertices({
229 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
230 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
231 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
232 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
233 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
234 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
235 });
236 auto vertex_buffer =
237 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
238 ASSERT_TRUE(vertex_buffer);
239
240 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
241 auto boston = CreateTextureForFixture("boston.jpg");
242 ASSERT_TRUE(bridge && boston);
243 const std::unique_ptr<const Sampler>& sampler =
244 context->GetSamplerLibrary()->GetSampler({});
245 ASSERT_TRUE(sampler);
246
247 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
248 SinglePassCallback callback = [&](RenderPass& pass) {
249 for (size_t i = 0; i < 1; i++) {
250 for (size_t j = 0; j < 1; j++) {
251 pass.SetCommandLabel("Box");
252 pass.SetPipeline(box_pipeline);
253 pass.SetVertexBuffer(vertex_buffer);
254
255 FS::FrameInfo frame_info;
256 frame_info.current_time = GetSecondsElapsed();
257 frame_info.cursor_position = GetCursorPosition();
258 frame_info.window_size.x = GetWindowSize().width;
259 frame_info.window_size.y = GetWindowSize().height;
260
261 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
262 FS::BindContents1(pass, boston, sampler);
263 FS::BindContents2(pass, bridge, sampler);
264
265 VS::UniformBuffer uniforms;
266 EXPECT_EQ(pass.GetOrthographicTransform(),
267 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
268 uniforms.mvp = pass.GetOrthographicTransform() *
269 Matrix::MakeScale(GetContentScale()) *
270 Matrix::MakeTranslation({i * 50.0f, j * 50.0f, 0.0f});
271 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
272 if (!pass.Draw().ok()) {
273 return false;
274 }
275 }
276 }
277
278 host_buffer->Reset();
279 return true;
280 };
281 OpenPlaygroundHere(callback);
282 }

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

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderPerspectiveCube |
| ) |  |

Definition at line 122 of file renderer_unittests.cc.

122 {
123 using VS = ColorsVertexShader;
124 using FS = ColorsFragmentShader;
125 auto context = GetContext();
126 ASSERT_TRUE(context);
127 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
128 ASSERT_TRUE(desc.has_value());
129 desc->SetCullMode(CullMode::kBackFace);
130 desc->SetWindingOrder(WindingOrder::kCounterClockwise);
131 desc->SetSampleCount(SampleCount::kCount4);
132 desc->SetStencilAttachmentDescriptors(std::nullopt);
133 auto pipeline =
134 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
135 ASSERT_TRUE(pipeline);
136
137 struct Cube {
138 VS::PerVertexData vertices[8] = {
139 // -Z
140 {{-1, -1, -1}, Color::Red()},
141 {{1, -1, -1}, Color::Yellow()},
142 {{1, 1, -1}, Color::Green()},
143 {{-1, 1, -1}, Color::Blue()},
144 // +Z
145 {{-1, -1, 1}, Color::Green()},
146 {{1, -1, 1}, Color::Blue()},
147 {{1, 1, 1}, Color::Red()},
148 {{-1, 1, 1}, Color::Yellow()},
149 };
150 uint16_t indices[36] = {
151 1, 5, 2, 2, 5, 6, // +X
152 4, 0, 7, 7, 0, 3, // -X
153 4, 5, 0, 0, 5, 1, // +Y
154 3, 2, 7, 7, 2, 6, // -Y
155 5, 4, 6, 6, 4, 7, // +Z
156 0, 1, 3, 3, 1, 2, // -Z
157 };
158 } cube;
159
160 VertexBuffer vertex_buffer;
161 {
162 auto device_buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
163 reinterpret_cast<uint8_t*>(&cube), sizeof(cube));
164 vertex_buffer.vertex_buffer = {
165 .buffer = device_buffer,
166 .range = Range(offsetof(Cube, vertices), sizeof(Cube::vertices))};
167 vertex_buffer.index_buffer = {
168 .buffer = device_buffer,
169 .range = Range(offsetof(Cube, indices), sizeof(Cube::indices))};
170 vertex_buffer.vertex_count = 36;
171 vertex_buffer.index_type = IndexType::k16bit;
172 }
173
174 const std::unique_ptr<const Sampler>& sampler =
175 context->GetSamplerLibrary()->GetSampler({});
176 ASSERT_TRUE(sampler);
177
178 Vector3 euler_angles;
179 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
180 SinglePassCallback callback = [&](RenderPass& pass) {
181 static Degrees fov_y(60);
182 static Scalar distance = 10;
183
184 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
185 ImGui::SliderFloat("Field of view", &fov_y.degrees, 0, 180);
186 ImGui::SliderFloat("Camera distance", &distance, 0, 30);
187 ImGui::End();
188
189 pass.SetCommandLabel("Perspective Cube");
190 pass.SetPipeline(pipeline);
191 pass.SetVertexBuffer(vertex_buffer);
192
193 VS::UniformBuffer uniforms;
194 Scalar time = GetSecondsElapsed();
195 euler_angles = Vector3(0.19 * time, 0.7 * time, 0.43 * time);
196
197 uniforms.mvp =
198 Matrix::MakePerspective(fov_y, pass.GetRenderTargetSize(), 0, 10) *
199 Matrix::MakeTranslation({0, 0, distance}) *
200 Matrix::MakeRotationX(Radians(euler_angles.x)) *
201 Matrix::MakeRotationY(Radians(euler_angles.y)) *
202 Matrix::MakeRotationZ(Radians(euler_angles.z));
203 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
204
205 host_buffer->Reset();
206 return pass.Draw().ok();
207 };
208 OpenPlaygroundHere(callback);
209 }

References impeller::Color::Blue(), impeller::BufferView::buffer, impeller::HostBuffer::Create(), impeller::Degrees::degrees, impeller::saturated::distance, impeller::Color::Green(), impeller::VertexBuffer::index_buffer, impeller::VertexBuffer::index_type, 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::Color::Red(), impeller::VertexBuffer::vertex_buffer, impeller::VertexBuffer::vertex_count, impeller::Vector3::x, impeller::Vector3::y, impeller::Color::Yellow(), and impeller::Vector3::z.

## ◆ TEST_P() [388/419]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderToTexture |
| ) |  |

Definition at line 284 of file renderer_unittests.cc.

284 {
285 using VS = BoxFadeVertexShader;
286 using FS = BoxFadeFragmentShader;
287 auto context = GetContext();
288 ASSERT_TRUE(context);
289 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
290 auto pipeline_desc =
291 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
292 pipeline_desc->SetSampleCount(SampleCount::kCount1);
293 pipeline_desc->ClearDepthAttachment();
294 pipeline_desc->SetStencilPixelFormat(PixelFormat::kS8UInt);
295
296 ASSERT_TRUE(pipeline_desc.has_value());
297 auto box_pipeline =
298 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
299 ASSERT_TRUE(box_pipeline);
300 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
301
302 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
303 vertex_builder.SetLabel("Box");
304 vertex_builder.AddVertices({
305 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
306 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
307 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
308 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
309 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
310 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
311 });
312 auto vertex_buffer =
313 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
314 ASSERT_TRUE(vertex_buffer);
315
316 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
317 auto boston = CreateTextureForFixture("boston.jpg");
318 ASSERT_TRUE(bridge && boston);
319 const std::unique_ptr<const Sampler>& sampler =
320 context->GetSamplerLibrary()->GetSampler({});
321 ASSERT_TRUE(sampler);
322
323 std::shared_ptr<RenderPass> r2t_pass;
324 auto cmd_buffer = context->CreateCommandBuffer();
325 ASSERT_TRUE(cmd_buffer);
326 {
327 ColorAttachment color0;
328 color0.load_action = LoadAction::kClear;
329 color0.store_action = StoreAction::kStore;
330
331 TextureDescriptor texture_descriptor;
332 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u), nullptr);
333 texture_descriptor.format =
334 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
335 texture_descriptor.storage_mode = StorageMode::kHostVisible;
336 texture_descriptor.size = {400, 400};
337 texture_descriptor.mip_count = 1u;
338 texture_descriptor.usage = TextureUsage::kRenderTarget;
339
340 color0.texture =
341 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
342
343 ASSERT_TRUE(color0.IsValid());
344
345 color0.texture->SetLabel("r2t_target");
346
347 StencilAttachment stencil0;
348 stencil0.load_action = LoadAction::kClear;
349 stencil0.store_action = StoreAction::kDontCare;
350 TextureDescriptor stencil_texture_desc;
351 stencil_texture_desc.storage_mode = StorageMode::kDeviceTransient;
352 stencil_texture_desc.size = texture_descriptor.size;
353 stencil_texture_desc.format = PixelFormat::kS8UInt;
354 stencil_texture_desc.usage = TextureUsage::kRenderTarget;
355 stencil0.texture =
356 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
357
358 RenderTarget r2t_desc;
359 r2t_desc.SetColorAttachment(color0, 0u);
360 r2t_desc.SetStencilAttachment(stencil0);
361 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
362 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
363 }
364
365 r2t_pass->SetCommandLabel("Box");
366 r2t_pass->SetPipeline(box_pipeline);
367 r2t_pass->SetVertexBuffer(vertex_buffer);
368
369 FS::FrameInfo frame_info;
370 frame_info.current_time = GetSecondsElapsed();
371 frame_info.cursor_position = GetCursorPosition();
372 frame_info.window_size.x = GetWindowSize().width;
373 frame_info.window_size.y = GetWindowSize().height;
374
375 FS::BindFrameInfo(*r2t_pass, host_buffer->EmplaceUniform(frame_info));
376 FS::BindContents1(*r2t_pass, boston, sampler);
377 FS::BindContents2(*r2t_pass, bridge, sampler);
378
379 VS::UniformBuffer uniforms;
380 uniforms.mvp = Matrix::MakeOrthographic(ISize{1024, 768}) *
381 Matrix::MakeTranslation({50.0f, 50.0f, 0.0f});
382 VS::BindUniformBuffer(*r2t_pass, host_buffer->EmplaceUniform(uniforms));
383 ASSERT_TRUE(r2t_pass->Draw().ok());
384 ASSERT_TRUE(r2t_pass->EncodeCommands());
385 }

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

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanSepiaToneThenSwizzleWithSubpasses |
| ) |  |

Definition at line 1416 of file renderer_unittests.cc.

1416 {
1417 // The GLES framebuffer fetch implementation currently does not support this.
1418 // TODO(chinmaygarde): revisit after the GLES framebuffer fetch capabilities
1419 // are clarified.
1420 if (GetParam() == PlaygroundBackend::kOpenGLES) {
1421 GTEST_SKIP_("Not supported on GLES.");
1422 }
1423
1424 // Define shader types
1425 using TextureVS = TextureVertexShader;
1426 using TextureFS = TextureFragmentShader;
1427
1428 using SwizzleVS = SepiaVertexShader;
1429 using SwizzleFS = SwizzleFragmentShader;
1430
1431 using SepiaVS = SepiaVertexShader;
1432 using SepiaFS = SepiaFragmentShader;
1433
1434 auto context = GetContext();
1435 ASSERT_TRUE(context);
1436
1437 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1438 GTEST_SKIP_(
1439 "This test uses framebuffer fetch and the backend doesn't support it.");
1440 return;
1441 }
1442
1443 // Create pipelines.
1444 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1445 auto swizzle_pipeline = CreateDefaultPipeline<SwizzleVS, SwizzleFS>(context);
1446 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1447
1448 ASSERT_TRUE(texture_pipeline);
1449 ASSERT_TRUE(swizzle_pipeline);
1450 ASSERT_TRUE(sepia_pipeline);
1451
1452 // Vertex buffer builders.
1453 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1454 texture_vtx_builder.AddVertices({
1455 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1456 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1457 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1458 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1459 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1460 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1461 });
1462
1463 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1464 sepia_vtx_builder.AddVertices({
1465 {{100, 100, 0.0}}, // 1
1466 {{800, 100, 0.0}}, // 2
1467 {{800, 800, 0.0}}, // 3
1468 {{100, 100, 0.0}}, // 1
1469 {{800, 800, 0.0}}, // 3
1470 {{100, 800, 0.0}}, // 4
1471 });
1472
1473 auto boston = CreateTextureForFixture("boston.jpg");
1474 ASSERT_TRUE(boston);
1475
1476 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1477 ASSERT_TRUE(sampler);
1478
1479 SinglePassCallback callback = [&](RenderPass& pass) {
1480 auto buffer = HostBuffer::Create(context->GetResourceAllocator());
1481
1482 // Draw the texture.
1483 {
1484 pass.SetPipeline(texture_pipeline);
1485 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1486 *context->GetResourceAllocator()));
1487 TextureVS::UniformBuffer uniforms;
1488 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1489 Matrix::MakeScale(GetContentScale());
1490 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1491 TextureFS::BindTextureContents(pass, boston, sampler);
1492 if (!pass.Draw().ok()) {
1493 return false;
1494 }
1495 }
1496
1497 // Draw the sepia toner.
1498 {
1499 pass.SetPipeline(sepia_pipeline);
1500 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1501 *context->GetResourceAllocator()));
1502 SepiaVS::UniformBuffer uniforms;
1503 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1504 Matrix::MakeScale(GetContentScale());
1505 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1506 if (!pass.Draw().ok()) {
1507 return false;
1508 }
1509 }
1510
1511 // Draw the swizzle.
1512 {
1513 pass.SetPipeline(swizzle_pipeline);
1514 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1515 *context->GetResourceAllocator()));
1516 SwizzleVS::UniformBuffer uniforms;
1517 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1518 Matrix::MakeScale(GetContentScale());
1519 SwizzleVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1520 if (!pass.Draw().ok()) {
1521 return false;
1522 }
1523 }
1524
1525 return true;
1526 };
1527 OpenPlaygroundHere(callback);
1528 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kOpenGLES, impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [390/419]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanSepiaToneWithSubpasses |
| ) |  |

Definition at line 1321 of file renderer_unittests.cc.

1321 {
1322 // The GLES framebuffer fetch implementation currently does not support this.
1323 // TODO(chinmaygarde): revisit after the GLES framebuffer fetch capabilities
1324 // are clarified.
1325 if (GetParam() == PlaygroundBackend::kOpenGLES) {
1326 GTEST_SKIP_("Not supported on GLES.");
1327 }
1328
1329 // Define shader types
1330 using TextureVS = TextureVertexShader;
1331 using TextureFS = TextureFragmentShader;
1332
1333 using SepiaVS = SepiaVertexShader;
1334 using SepiaFS = SepiaFragmentShader;
1335
1336 auto context = GetContext();
1337 ASSERT_TRUE(context);
1338
1339 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1340 GTEST_SKIP_(
1341 "This test uses framebuffer fetch and the backend doesn't support it.");
1342 return;
1343 }
1344
1345 // Create pipelines.
1346 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1347 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1348
1349 ASSERT_TRUE(texture_pipeline);
1350 ASSERT_TRUE(sepia_pipeline);
1351
1352 // Vertex buffer builders.
1353 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1354 texture_vtx_builder.AddVertices({
1355 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1356 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1357 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1358 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1359 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1360 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1361 });
1362
1363 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1364 sepia_vtx_builder.AddVertices({
1365 {{100, 100, 0.0}}, // 1
1366 {{800, 100, 0.0}}, // 2
1367 {{800, 800, 0.0}}, // 3
1368 {{100, 100, 0.0}}, // 1
1369 {{800, 800, 0.0}}, // 3
1370 {{100, 800, 0.0}}, // 4
1371 });
1372
1373 auto boston = CreateTextureForFixture("boston.jpg");
1374 ASSERT_TRUE(boston);
1375
1376 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1377 ASSERT_TRUE(sampler);
1378
1379 SinglePassCallback callback = [&](RenderPass& pass) {
1380 auto buffer = HostBuffer::Create(context->GetResourceAllocator());
1381
1382 // Draw the texture.
1383 {
1384 pass.SetPipeline(texture_pipeline);
1385 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1386 *context->GetResourceAllocator()));
1387 TextureVS::UniformBuffer uniforms;
1388 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1389 Matrix::MakeScale(GetContentScale());
1390 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1391 TextureFS::BindTextureContents(pass, boston, sampler);
1392 if (!pass.Draw().ok()) {
1393 return false;
1394 }
1395 }
1396
1397 // Draw the sepia toner.
1398 {
1399 pass.SetPipeline(sepia_pipeline);
1400 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1401 *context->GetResourceAllocator()));
1402 SepiaVS::UniformBuffer uniforms;
1403 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1404 Matrix::MakeScale(GetContentScale());
1405 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1406 if (!pass.Draw().ok()) {
1407 return false;
1408 }
1409 }
1410
1411 return true;
1412 };
1413 OpenPlaygroundHere(callback);
1414 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kOpenGLES, impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [391/419]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexBehavior |
| ) |  |

Definition at line 1038 of file renderer_unittests.cc.

1038 {
1039 using VS = BoxFadeVertexShader;
1040
1041 // Do not create any index buffer if no indices were provided.
1042 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1043 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::kNone);
1044 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::kNone.

## ◆ TEST_P() [392/419]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexSize |
| ) |  |

Definition at line 1028 of file renderer_unittests.cc.

1028 {
1029 using VS = BoxFadeVertexShader;
1030
1031 // Default to 16bit index buffer size, as this is a reasonable default and
1032 // supported on all backends without extensions.
1033 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1034 vertex_builder.AppendIndex(0u);
1035 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::k16bit);
1036 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendIndex(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::k16bit.

## ◆ TEST_P() [393/419]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | InactiveUniforms |
| ) |  |

Definition at line 944 of file renderer_unittests.cc.

944 {
945 using VS = InactiveUniformsVertexShader;
946 using FS = InactiveUniformsFragmentShader;
947
948 auto context = GetContext();
949 auto pipeline_descriptor =
950 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
951 ASSERT_TRUE(pipeline_descriptor.has_value());
952 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
953 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
954 auto pipeline =
955 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
956 ASSERT_TRUE(pipeline && pipeline->IsValid());
957
958 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
959 SinglePassCallback callback = [&](RenderPass& pass) {
960 auto size = pass.GetRenderTargetSize();
961
962 pass.SetPipeline(pipeline);
963 pass.SetCommandLabel("Inactive Uniform");
964
965 VertexBufferBuilder<VS::PerVertexData> builder;
966 builder.AddVertices({{Point()},
967 {Point(0, size.height)},
968 {Point(size.width, 0)},
969 {Point(size.width, 0)},
970 {Point(0, size.height)},
971 {Point(size.width, size.height)}});
972 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
973
974 VS::FrameInfo frame_info;
975 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
976 frame_info.mvp =
977 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
978 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
979
980 FS::FragInfo fs_uniform = {.unused_color = Color::Red(),
981 .color = Color::Green()};
982 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
983
984 pass.Draw().ok();
985 host_buffer->Reset();
986 return true;
987 };
988 OpenPlaygroundHere(callback);
989 }

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

impeller::testing::TEST_P | ( | RendererTest | ,
|  | RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat |
| ) |  |

Definition at line 1288 of file renderer_unittests.cc.

1289 {
1290 auto context = GetContext();
1291 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1292 GetContext()->GetResourceAllocator());
1293
1294 RenderTarget render_target = render_target_cache->CreateOffscreenMSAA(
1295 *context, {100, 100}, /*mip_count=*/1);
1296 EXPECT_EQ(render_target.GetDepthAttachment()
1297 ->texture->GetTextureDescriptor()
1298 .format,
1299 GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat());
1300 }

References impeller::RenderTarget::GetDepthAttachment().

## ◆ TEST_P() [395/419]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | StencilMask |
| ) |  |

Definition at line 1116 of file renderer_unittests.cc.

1116 {
1117 using VS = BoxFadeVertexShader;
1118 using FS = BoxFadeFragmentShader;
1119 auto context = GetContext();
1120 ASSERT_TRUE(context);
1121 using BoxFadePipelineBuilder = PipelineBuilder<VS, FS>;
1122 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1123 ASSERT_TRUE(desc.has_value());
1124
1125 // Vertex buffer.
1126 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1127 vertex_builder.SetLabel("Box");
1128 vertex_builder.AddVertices({
1129 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1130 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1131 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1132 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1133 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1134 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1135 });
1136 auto vertex_buffer =
1137 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
1138 ASSERT_TRUE(vertex_buffer);
1139
1140 desc->SetSampleCount(SampleCount::kCount4);
1141 desc->SetStencilAttachmentDescriptors(std::nullopt);
1142
1143 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
1144 auto boston = CreateTextureForFixture("boston.jpg");
1145 ASSERT_TRUE(bridge && boston);
1146 const std::unique_ptr<const Sampler>& sampler =
1147 context->GetSamplerLibrary()->GetSampler({});
1148 ASSERT_TRUE(sampler);
1149
1150 static bool mirror = false;
1151 static int stencil_reference_write = 0xFF;
1152 static int stencil_reference_read = 0x1;
1153 std::vector<uint8_t> stencil_contents;
1154 static int last_stencil_contents_reference_value = 0;
1155 static int current_front_compare =
1156 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1157 static int current_back_compare =
1158 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1159
1160 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
1161 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
1162 auto buffer = context->CreateCommandBuffer();
1163 if (!buffer) {
1164 return false;
1165 }
1166 buffer->SetLabel("Playground Command Buffer");
1167
1168 {
1169 // Configure the stencil attachment for the test.
1170 RenderTarget::AttachmentConfig stencil_config;
1171 stencil_config.load_action = LoadAction::kLoad;
1172 stencil_config.store_action = StoreAction::kDontCare;
1173 stencil_config.storage_mode = StorageMode::kHostVisible;
1174 render_target.SetupDepthStencilAttachments(
1175 *context, *context->GetResourceAllocator(),
1176 render_target.GetRenderTargetSize(), true, "stencil", stencil_config);
1177 // Fill the stencil buffer with an checkerboard pattern.
1178 const auto target_width = render_target.GetRenderTargetSize().width;
1179 const auto target_height = render_target.GetRenderTargetSize().height;
1180 const size_t target_size = target_width * target_height;
1181 if (stencil_contents.size() != target_size ||
1182 last_stencil_contents_reference_value != stencil_reference_write) {
1183 stencil_contents.resize(target_size);
1184 last_stencil_contents_reference_value = stencil_reference_write;
1185 for (int y = 0; y < target_height; y++) {
1186 for (int x = 0; x < target_width; x++) {
1187 const auto index = y * target_width + x;
1188 const auto kCheckSize = 64;
1189 const auto value =
1190 (((y / kCheckSize) + (x / kCheckSize)) % 2 == 0) *
1191 stencil_reference_write;
1192 stencil_contents[index] = value;
1193 }
1194 }
1195 }
1196 if (!render_target.GetStencilAttachment()->texture->SetContents(
1197 stencil_contents.data(), stencil_contents.size(), 0, false)) {
1198 VALIDATION_LOG << "Could not upload stencil contents to device memory";
1199 return false;
1200 }
1201 auto pass = buffer->CreateRenderPass(render_target);
1202 if (!pass) {
1203 return false;
1204 }
1205 pass->SetLabel("Stencil Buffer");
1206 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1207 ImGui::SliderInt("Stencil Write Value", &stencil_reference_write, 0,
1208 0xFF);
1209 ImGui::SliderInt("Stencil Compare Value", &stencil_reference_read, 0,
1210 0xFF);
1211 ImGui::Checkbox("Back face mode", &mirror);
1212 ImGui::ListBox("Front face compare function", &current_front_compare,
1213 CompareFunctionUI().labels(), CompareFunctionUI().size());
1214 ImGui::ListBox("Back face compare function", &current_back_compare,
1215 CompareFunctionUI().labels(), CompareFunctionUI().size());
1216 ImGui::End();
1217
1218 StencilAttachmentDescriptor front;
1219 front.stencil_compare =
1220 CompareFunctionUI().FunctionOf(current_front_compare);
1221 StencilAttachmentDescriptor back;
1222 back.stencil_compare =
1223 CompareFunctionUI().FunctionOf(current_back_compare);
1224 desc->SetStencilAttachmentDescriptors(front, back);
1225 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
1226
1227 assert(pipeline && pipeline->IsValid());
1228
1229 pass->SetCommandLabel("Box");
1230 pass->SetPipeline(pipeline);
1231 pass->SetStencilReference(stencil_reference_read);
1232 pass->SetVertexBuffer(vertex_buffer);
1233
1234 VS::UniformBuffer uniforms;
1235 EXPECT_EQ(pass->GetOrthographicTransform(),
1236 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
1237 uniforms.mvp = pass->GetOrthographicTransform() *
1238 Matrix::MakeScale(GetContentScale());
1239 if (mirror) {
1240 uniforms.mvp = Matrix::MakeScale(Vector2(-1, 1)) * uniforms.mvp;
1241 }
1242 VS::BindUniformBuffer(*pass, host_buffer->EmplaceUniform(uniforms));
1243
1244 FS::FrameInfo frame_info;
1245 frame_info.current_time = GetSecondsElapsed();
1246 frame_info.cursor_position = GetCursorPosition();
1247 frame_info.window_size.x = GetWindowSize().width;
1248 frame_info.window_size.y = GetWindowSize().height;
1249
1250 FS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
1251 FS::BindContents1(*pass, boston, sampler);
1252 FS::BindContents2(*pass, bridge, sampler);
1253 if (!pass->Draw().ok()) {
1254 return false;
1255 }
1256 pass->EncodeCommands();
1257 }
1258
1259 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
1260 return false;
1261 }
1262 host_buffer->Reset();
1263 return true;
1264 };
1265 OpenPlaygroundHere(callback);
1266 }

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, and VALIDATION_LOG.

## ◆ TEST_P() [396/419]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | TheImpeller |
| ) |  |

Definition at line 825 of file renderer_unittests.cc.

825 {
826 using VS = ImpellerVertexShader;
827 using FS = ImpellerFragmentShader;
828
829 auto context = GetContext();
830 auto pipeline_descriptor =
831 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
832 ASSERT_TRUE(pipeline_descriptor.has_value());
833 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
834 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
835 auto pipeline =
836 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
837 ASSERT_TRUE(pipeline && pipeline->IsValid());
838
839 auto blue_noise = CreateTextureForFixture("blue_noise.png");
840 SamplerDescriptor noise_sampler_desc;
841 noise_sampler_desc.width_address_mode = SamplerAddressMode::kRepeat;
842 noise_sampler_desc.height_address_mode = SamplerAddressMode::kRepeat;
843 const std::unique_ptr<const Sampler>& noise_sampler =
844 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
845
846 auto cube_map = CreateTextureCubeForFixture(
847 {"table_mountain_px.png", "table_mountain_nx.png",
848 "table_mountain_py.png", "table_mountain_ny.png",
849 "table_mountain_pz.png", "table_mountain_nz.png"});
850 const std::unique_ptr<const Sampler>& cube_map_sampler =
851 context->GetSamplerLibrary()->GetSampler({});
852 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
853
854 SinglePassCallback callback = [&](RenderPass& pass) {
855 auto size = pass.GetRenderTargetSize();
856
857 pass.SetPipeline(pipeline);
858 pass.SetCommandLabel("Impeller SDF scene");
859 VertexBufferBuilder<VS::PerVertexData> builder;
860 builder.AddVertices({{Point()},
861 {Point(0, size.height)},
862 {Point(size.width, 0)},
863 {Point(size.width, 0)},
864 {Point(0, size.height)},
865 {Point(size.width, size.height)}});
866 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
867
868 VS::FrameInfo frame_info;
869 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
870 frame_info.mvp = pass.GetOrthographicTransform();
871 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
872
873 FS::FragInfo fs_uniform;
874 fs_uniform.texture_size = Point(size);
875 fs_uniform.time = GetSecondsElapsed();
876 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
877 FS::BindBlueNoise(pass, blue_noise, noise_sampler);
878 FS::BindCubeMap(pass, cube_map, cube_map_sampler);
879
880 pass.Draw().ok();
881 host_buffer->Reset();
882 return true;
883 };
884 OpenPlaygroundHere(callback);
885 }

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

impeller::testing::TEST_P | ( | RendererTest | ,
|  | VertexBufferBuilder |
| ) |  |

Definition at line 1046 of file renderer_unittests.cc.

1046 {
1047 // Does not create index buffer if one is provided.
1048 using VS = BoxFadeVertexShader;
1049 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1050 vertex_builder.SetLabel("Box");
1051 vertex_builder.AddVertices({
1052 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1053 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1054 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1055 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1056 });
1057 vertex_builder.AppendIndex(0);
1058 vertex_builder.AppendIndex(1);
1059 vertex_builder.AppendIndex(2);
1060 vertex_builder.AppendIndex(1);
1061 vertex_builder.AppendIndex(2);
1062 vertex_builder.AppendIndex(3);
1063
1064 ASSERT_EQ(vertex_builder.GetIndexCount(), 6u);
1065 ASSERT_EQ(vertex_builder.GetVertexCount(), 4u);
1066 }

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

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CachedTextureGetsNewAttachmentConfig |
| ) |  |

Definition at line 90 of file render_target_cache_unittests.cc.

90 {
91 auto render_target_cache =
92 RenderTargetCache(GetContext()->GetResourceAllocator());
93
94 render_target_cache.Start();
95 RenderTarget::AttachmentConfig color_attachment_config =
96 RenderTarget::kDefaultColorAttachmentConfig;
97 RenderTarget target1 = render_target_cache.CreateOffscreen(
98 *GetContext(), {100, 100}, 1, "Offscreen1", color_attachment_config);
99 render_target_cache.End();
100
101 render_target_cache.Start();
102 color_attachment_config.clear_color = Color::Red();
103 RenderTarget target2 = render_target_cache.CreateOffscreen(
104 *GetContext(), {100, 100}, 1, "Offscreen2", color_attachment_config);
105 render_target_cache.End();
106
107 auto color1 = target1.GetColorAttachments().find(0)->second;
108 auto color2 = target2.GetColorAttachments().find(0)->second;
109 // The second color attachment should reuse the first attachment's texture
110 // but with attributes from the second AttachmentConfig.
111 EXPECT_EQ(color2.texture, color1.texture);
112 EXPECT_EQ(color2.clear_color, Color::Red());
113 }

References impeller::RenderTarget::AttachmentConfig::clear_color, impeller::RenderTarget::GetColorAttachments(), impeller::RenderTarget::kDefaultColorAttachmentConfig, and impeller::Color::Red().

## ◆ TEST_P() [399/419]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CachesUsedTexturesAcrossFrames |
| ) |  |

Definition at line 51 of file render_target_cache_unittests.cc.

51 {
52 auto render_target_cache =
53 RenderTargetCache(GetContext()->GetResourceAllocator());
54
55 render_target_cache.Start();
56 // Create two render targets of the same exact size/shape. Both should be
57 // marked as used this frame, so the cached data set will contain two.
58 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
59 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
60
61 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
62
63 render_target_cache.End();
64 render_target_cache.Start();
65
66 // Next frame, only create one texture. The set will still contain two,
67 // but one will be removed at the end of the frame.
68 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
69 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
70
71 render_target_cache.End();
72 EXPECT_EQ(render_target_cache.CachedTextureCount(), 1u);
73 }

## ◆ TEST_P() [400/419]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CreateWithEmptySize |
| ) |  |

Definition at line 115 of file render_target_cache_unittests.cc.

115 {
116 auto render_target_cache =
117 RenderTargetCache(GetContext()->GetResourceAllocator());
118
119 render_target_cache.Start();
120 RenderTarget empty_target =
121 render_target_cache.CreateOffscreen(*GetContext(), {100, 0}, 1);
122 RenderTarget empty_target_msaa =
123 render_target_cache.CreateOffscreenMSAA(*GetContext(), {0, 0}, 1);
124 render_target_cache.End();
125
126 {
127 ScopedValidationDisable disable_validation;
128 EXPECT_FALSE(empty_target.IsValid());
129 EXPECT_FALSE(empty_target_msaa.IsValid());
130 }
131 }

References impeller::RenderTarget::IsValid().

## ◆ TEST_P() [401/419]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | DoesNotPersistFailedAllocations |
| ) |  |

Definition at line 75 of file render_target_cache_unittests.cc.

75 {
76 ScopedValidationDisable disable;
77 auto allocator = std::make_shared<TestAllocator>();
78 auto render_target_cache = RenderTargetCache(allocator);
79
80 render_target_cache.Start();
81 allocator->should_fail = true;
82
83 auto render_target =
84 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
85
86 EXPECT_FALSE(render_target.IsValid());
87 EXPECT_EQ(render_target_cache.CachedTextureCount(), 0u);
88 }

## ◆ TEST_P() [402/419]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanCreatePipelineFromRuntimeStage |
| ) |  |

Definition at line 262 of file runtime_stage_unittests.cc.

262 {
263 auto stages = OpenAssetAsRuntimeStage("ink_sparkle.frag.iplr");
264 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
265
266 ASSERT_TRUE(stage);
267 ASSERT_NE(stage, nullptr);
268 ASSERT_TRUE(RegisterStage(*stage));
269 auto library = GetContext()->GetShaderLibrary();
270 using VS = RuntimeEffectVertexShader;
271 PipelineDescriptor desc;
272 desc.SetLabel("Runtime Stage InkSparkle");
273 desc.AddStageEntrypoint(
274 library->GetFunction(VS::kEntrypointName, ShaderStage::kVertex));
275 desc.AddStageEntrypoint(
276 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment));
277 auto vertex_descriptor = std::make_shared<VertexDescriptor>();
278 vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
279 VS::kInterleavedBufferLayout);
280
281 std::array<DescriptorSetLayout, 2> descriptor_set_layouts = {
282 VS::kDescriptorSetLayouts[0],
283 DescriptorSetLayout{
284 .binding = 64u,
285 .descriptor_type = DescriptorType::kUniformBuffer,
286 .shader_stage = ShaderStage::kFragment,
287 },
288 };
289 vertex_descriptor->RegisterDescriptorSetLayouts(descriptor_set_layouts);
290
291 desc.SetVertexDescriptor(std::move(vertex_descriptor));
292 ColorAttachmentDescriptor color0;
293 color0.format = GetContext()->GetCapabilities()->GetDefaultColorFormat();
294 StencilAttachmentDescriptor stencil0;
295 stencil0.stencil_compare = CompareFunction::kEqual;
296 desc.SetColorAttachmentDescriptor(0u, color0);
297 desc.SetStencilAttachmentDescriptors(stencil0);
298 const auto stencil_fmt =
299 GetContext()->GetCapabilities()->GetDefaultStencilFormat();
300 desc.SetStencilPixelFormat(stencil_fmt);
301 auto pipeline = GetContext()->GetPipelineLibrary()->GetPipeline(desc).Get();
302 ASSERT_NE(pipeline, nullptr);
303 }

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

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadUniforms |
| ) |  |

Definition at line 54 of file runtime_stage_unittests.cc.

54 {
55 const std::shared_ptr<fml::Mapping> fixture =
56 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
57 ASSERT_TRUE(fixture);
58 ASSERT_GT(fixture->GetSize(), 0u);
59 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
60 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
61
62 ASSERT_TRUE(stage->IsValid());
63 switch (GetBackend()) {
64 case PlaygroundBackend::kMetal:
65 case PlaygroundBackend::kOpenGLES: {
66 ASSERT_EQ(stage->GetUniforms().size(), 17u);
67 {
68 auto uni = stage->GetUniform("u_color");
69 ASSERT_NE(uni, nullptr);
70 EXPECT_EQ(uni->dimensions.rows, 4u);
71 EXPECT_EQ(uni->dimensions.cols, 1u);
72 EXPECT_EQ(uni->location, 0u);
73 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
74 }
75 {
76 auto uni = stage->GetUniform("u_alpha");
77 ASSERT_NE(uni, nullptr);
78 EXPECT_EQ(uni->dimensions.rows, 1u);
79 EXPECT_EQ(uni->dimensions.cols, 1u);
80 EXPECT_EQ(uni->location, 1u);
81 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
82 }
83 {
84 auto uni = stage->GetUniform("u_sparkle_color");
85 ASSERT_NE(uni, nullptr);
86 EXPECT_EQ(uni->dimensions.rows, 4u);
87 EXPECT_EQ(uni->dimensions.cols, 1u);
88 EXPECT_EQ(uni->location, 2u);
89 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
90 }
91 {
92 auto uni = stage->GetUniform("u_sparkle_alpha");
93 ASSERT_NE(uni, nullptr);
94 EXPECT_EQ(uni->dimensions.rows, 1u);
95 EXPECT_EQ(uni->dimensions.cols, 1u);
96 EXPECT_EQ(uni->location, 3u);
97 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
98 }
99 {
100 auto uni = stage->GetUniform("u_blur");
101 ASSERT_NE(uni, nullptr);
102 EXPECT_EQ(uni->dimensions.rows, 1u);
103 EXPECT_EQ(uni->dimensions.cols, 1u);
104 EXPECT_EQ(uni->location, 4u);
105 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
106 }
107 {
108 auto uni = stage->GetUniform("u_radius_scale");
109 ASSERT_NE(uni, nullptr);
110 EXPECT_EQ(uni->dimensions.rows, 1u);
111 EXPECT_EQ(uni->dimensions.cols, 1u);
112 EXPECT_EQ(uni->location, 6u);
113 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
114 }
115 {
116 auto uni = stage->GetUniform("u_max_radius");
117 ASSERT_NE(uni, nullptr);
118 EXPECT_EQ(uni->dimensions.rows, 1u);
119 EXPECT_EQ(uni->dimensions.cols, 1u);
120 EXPECT_EQ(uni->location, 7u);
121 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
122 }
123 {
124 auto uni = stage->GetUniform("u_resolution_scale");
125 ASSERT_NE(uni, nullptr);
126 EXPECT_EQ(uni->dimensions.rows, 2u);
127 EXPECT_EQ(uni->dimensions.cols, 1u);
128 EXPECT_EQ(uni->location, 8u);
129 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
130 }
131 {
132 auto uni = stage->GetUniform("u_noise_scale");
133 ASSERT_NE(uni, nullptr);
134 EXPECT_EQ(uni->dimensions.rows, 2u);
135 EXPECT_EQ(uni->dimensions.cols, 1u);
136 EXPECT_EQ(uni->location, 9u);
137 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
138 }
139 {
140 auto uni = stage->GetUniform("u_noise_phase");
141 ASSERT_NE(uni, nullptr);
142 EXPECT_EQ(uni->dimensions.rows, 1u);
143 EXPECT_EQ(uni->dimensions.cols, 1u);
144 EXPECT_EQ(uni->location, 10u);
145 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
146 }
147
148 {
149 auto uni = stage->GetUniform("u_circle1");
150 ASSERT_NE(uni, nullptr);
151 EXPECT_EQ(uni->dimensions.rows, 2u);
152 EXPECT_EQ(uni->dimensions.cols, 1u);
153 EXPECT_EQ(uni->location, 11u);
154 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
155 }
156 {
157 auto uni = stage->GetUniform("u_circle2");
158 ASSERT_NE(uni, nullptr);
159 EXPECT_EQ(uni->dimensions.rows, 2u);
160 EXPECT_EQ(uni->dimensions.cols, 1u);
161 EXPECT_EQ(uni->location, 12u);
162 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
163 }
164 {
165 auto uni = stage->GetUniform("u_circle3");
166 ASSERT_NE(uni, nullptr);
167 EXPECT_EQ(uni->dimensions.rows, 2u);
168 EXPECT_EQ(uni->dimensions.cols, 1u);
169 EXPECT_EQ(uni->location, 13u);
170 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
171 }
172 {
173 auto uni = stage->GetUniform("u_rotation1");
174 ASSERT_NE(uni, nullptr);
175 EXPECT_EQ(uni->dimensions.rows, 2u);
176 EXPECT_EQ(uni->dimensions.cols, 1u);
177 EXPECT_EQ(uni->location, 14u);
178 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
179 }
180 {
181 auto uni = stage->GetUniform("u_rotation2");
182 ASSERT_NE(uni, nullptr);
183 EXPECT_EQ(uni->dimensions.rows, 2u);
184 EXPECT_EQ(uni->dimensions.cols, 1u);
185 EXPECT_EQ(uni->location, 15u);
186 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
187 }
188 {
189 auto uni = stage->GetUniform("u_rotation3");
190 ASSERT_NE(uni, nullptr);
191 EXPECT_EQ(uni->dimensions.rows, 2u);
192 EXPECT_EQ(uni->dimensions.cols, 1u);
193 EXPECT_EQ(uni->location, 16u);
194 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
195 }
196 break;
197 }
198 case PlaygroundBackend::kVulkan: {
199 EXPECT_EQ(stage->GetUniforms().size(), 1u);
200 auto uni = stage->GetUniform(RuntimeStage::kVulkanUBOName);
201 ASSERT_TRUE(uni);
202 EXPECT_EQ(uni->type, RuntimeUniformType::kStruct);
203 EXPECT_EQ(uni->struct_float_count, 32u);
204
205 // There are 36 4 byte chunks in the UBO: 32 for the 32 floats, and 4 for
206 // padding. Initialize a vector as if they'll all be floats, then manually
207 // set the few padding bytes. If the shader changes, the padding locations
208 // will change as well. For example, if `u_alpha` was moved to the end,
209 // three bytes of padding could potentially be dropped - or if some of the
210 // scalar floats were changed to vec2 or vec4s, or if any vec3s are
211 // introduced.
212 // This means 36 * 4 = 144 bytes total.
213
214 EXPECT_EQ(uni->GetSize(), 144u);
215 std::vector<uint8_t> layout(uni->GetSize() / sizeof(float), 1);
216 layout[5] = 0;
217 layout[6] = 0;
218 layout[7] = 0;
219 layout[23] = 0;
220
221 EXPECT_THAT(uni->struct_layout, ::testing::ElementsAreArray(layout));
222 break;
223 }
224 }
225 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kFloat, impeller::kMetal, impeller::kOpenGLES, impeller::kStruct, impeller::kVulkan, impeller::RuntimeStage::kVulkanUBOName, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [404/419]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadValidBlob |
| ) |  |

Definition at line 28 of file runtime_stage_unittests.cc.

28 {
29 const std::shared_ptr<fml::Mapping> fixture =
30 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
31 ASSERT_TRUE(fixture);
32 ASSERT_GT(fixture->GetSize(), 0u);
33 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
34 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
35 ASSERT_TRUE(stage->IsValid());
36 ASSERT_EQ(stage->GetShaderStage(), RuntimeShaderStage::kFragment);
37 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kFragment, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [405/419]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanRegisterStage |
| ) |  |

Definition at line 227 of file runtime_stage_unittests.cc.

227 {
228 const std::shared_ptr<fml::Mapping> fixture =
229 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
230 ASSERT_TRUE(fixture);
231 ASSERT_GT(fixture->GetSize(), 0u);
232 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
233 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
234 ASSERT_TRUE(stage->IsValid());
235 std::promise<bool> registration;
236 auto future = registration.get_future();
237 auto library = GetContext()->GetShaderLibrary();
238 library->RegisterFunction(
239 stage->GetEntrypoint(), //
240 ToShaderStage(stage->GetShaderStage()), //
241 stage->GetCodeMapping(), //
242 fml::MakeCopyable([reg = std::move(registration)](bool result) mutable {
243 reg.set_value(result);
244 }));
245 ASSERT_TRUE(future.get());
246 {
247 auto function =
248 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
249 ASSERT_NE(function, nullptr);
250 }
251
252 // Check if unregistering works.
253
254 library->UnregisterFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
255 {
256 auto function =
257 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
258 ASSERT_EQ(function, nullptr);
259 }
260 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kFragment, impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::ToShaderStage().

## ◆ TEST_P() [406/419]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanRejectInvalidBlob |
| ) |  |

Definition at line 39 of file runtime_stage_unittests.cc.

39 {
40 ScopedValidationDisable disable_validation;
41 const std::shared_ptr<fml::Mapping> fixture =
42 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
43 ASSERT_TRUE(fixture);
44 auto junk_allocation = std::make_shared<Allocation>();
45 ASSERT_TRUE(junk_allocation->Truncate(fixture->GetSize(), false));
46 // Not meant to be secure. Just reject obviously bad blobs using magic
47 // numbers.
48 ::memset(junk_allocation->GetBuffer(), 127, junk_allocation->GetLength());
49 auto stages = RuntimeStage::DecodeRuntimeStages(
50 CreateMappingFromAllocation(junk_allocation));
51 ASSERT_FALSE(stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())]);
52 }

References impeller::CreateMappingFromAllocation(), impeller::RuntimeStage::DecodeRuntimeStages(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [407/419]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | ContainsExpectedShaderTypes |
| ) |  |

Definition at line 305 of file runtime_stage_unittests.cc.

305 {
306 auto stages = OpenAssetAsRuntimeStage("ink_sparkle.frag.iplr");
307 // Right now, SkSL gets implicitly bundled regardless of what the build rule
308 // for this test requested. After
309 // https://github.com/flutter/flutter/issues/138919, this may require a build
310 // rule change or a new test.
311 EXPECT_TRUE(stages[RuntimeStageBackend::kSkSL]);
312
313 EXPECT_TRUE(stages[RuntimeStageBackend::kOpenGLES]);
314 EXPECT_TRUE(stages[RuntimeStageBackend::kMetal]);
315 EXPECT_TRUE(stages[RuntimeStageBackend::kVulkan]);
316 }

References impeller::kMetal, impeller::kOpenGLES, impeller::kSkSL, and impeller::kVulkan.

## ◆ TEST_P() [408/419]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | CanConvertTextBlob |
| ) |  |

Definition at line 41 of file typographer_unittests.cc.

41 {
42 SkFont font = flutter::testing::CreateTestFontOfSize(12);
43 auto blob = SkTextBlob::MakeFromString(
44 "the quick brown fox jumped over the lazy dog.", font);
45 ASSERT_TRUE(blob);
46 auto frame = MakeTextFrameFromTextBlobSkia(blob);
47 ASSERT_EQ(frame->GetRunCount(), 1u);
48 for (const auto& run : frame->GetRuns()) {
49 ASSERT_TRUE(run.IsValid());
50 ASSERT_EQ(run.GetGlyphCount(), 45u);
51 }
52 }

References impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [409/419]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | CanCreateGlyphAtlas |
| ) |  |

Definition at line 59 of file typographer_unittests.cc.

59 {
60 auto context = TypographerContextSkia::Make();
61 auto atlas_context = context->CreateGlyphAtlasContext();
62 ASSERT_TRUE(context && context->IsValid());
63 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
64 auto blob = SkTextBlob::MakeFromString("hello", sk_font);
65 ASSERT_TRUE(blob);
66 auto atlas = CreateGlyphAtlas(
67 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
68 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
69 ASSERT_NE(atlas, nullptr);
70 ASSERT_NE(atlas->GetTexture(), nullptr);
71 ASSERT_EQ(atlas->GetType(), GlyphAtlas::Type::kAlphaBitmap);
72 ASSERT_EQ(atlas->GetGlyphCount(), 4llu);
73
74 std::optional<impeller::ScaledFont> first_scaled_font;
75 std::optional<impeller::Glyph> first_glyph;
76 Rect first_rect;
77 atlas->IterateGlyphs([&](const ScaledFont& scaled_font, const Glyph& glyph,
78 const Rect& rect) -> bool {
79 first_scaled_font = scaled_font;
80 first_glyph = glyph;
81 first_rect = rect;
82 return false;
83 });
84
85 ASSERT_TRUE(first_scaled_font.has_value());
86 ASSERT_TRUE(atlas
87 ->FindFontGlyphBounds(
88 {first_scaled_font.value(), first_glyph.value()})
89 .has_value());
90 }

References CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [410/419]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | CanCreateRenderContext |
| ) |  |

Definition at line 54 of file typographer_unittests.cc.

54 {
55 auto context = TypographerContextSkia::Make();
56 ASSERT_TRUE(context && context->IsValid());
57 }

References impeller::TypographerContextSkia::Make().

## ◆ TEST_P() [411/419]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasIsRecycledIfUnchanged |
| ) |  |

Definition at line 147 of file typographer_unittests.cc.

147 {
148 auto context = TypographerContextSkia::Make();
149 auto atlas_context = context->CreateGlyphAtlasContext();
150 ASSERT_TRUE(context && context->IsValid());
151 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
152 auto blob = SkTextBlob::MakeFromString("spooky skellingtons", sk_font);
153 ASSERT_TRUE(blob);
154 auto atlas = CreateGlyphAtlas(
155 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
156 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
157 ASSERT_NE(atlas, nullptr);
158 ASSERT_NE(atlas->GetTexture(), nullptr);
159 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
160
161 // now attempt to re-create an atlas with the same text blob.
162
163 auto next_atlas = CreateGlyphAtlas(
164 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
165 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
166 ASSERT_EQ(atlas, next_atlas);
167 ASSERT_EQ(atlas_context->GetGlyphAtlas(), atlas);
168 }

References CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [412/419]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasTextureIsRecreatedIfTypeChanges |
| ) |  |

Definition at line 247 of file typographer_unittests.cc.

247 {
248 auto context = TypographerContextSkia::Make();
249 auto atlas_context = context->CreateGlyphAtlasContext();
250 ASSERT_TRUE(context && context->IsValid());
251 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
252 auto blob = SkTextBlob::MakeFromString("spooky 1", sk_font);
253 ASSERT_TRUE(blob);
254 auto atlas = CreateGlyphAtlas(
255 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
256 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
257 auto old_packer = atlas_context->GetRectPacker();
258
259 ASSERT_NE(atlas, nullptr);
260 ASSERT_NE(atlas->GetTexture(), nullptr);
261 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
262
263 auto* first_texture = atlas->GetTexture().get();
264
265 // now create a new glyph atlas with an identical blob,
266 // but change the type.
267
268 auto blob2 = SkTextBlob::MakeFromString("spooky 1", sk_font);
269 auto next_atlas = CreateGlyphAtlas(
270 *GetContext(), context.get(), GlyphAtlas::Type::kColorBitmap, 1.0f,
271 atlas_context, *MakeTextFrameFromTextBlobSkia(blob2));
272 ASSERT_NE(atlas, next_atlas);
273 auto* second_texture = next_atlas->GetTexture().get();
274
275 auto new_packer = atlas_context->GetRectPacker();
276
277 ASSERT_NE(second_texture, first_texture);
278 ASSERT_NE(old_packer, new_packer);
279 }

References CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::GlyphAtlas::kColorBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [413/419]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasTextureIsRecycledIfUnchanged |
| ) |  |

Definition at line 214 of file typographer_unittests.cc.

214 {
215 auto context = TypographerContextSkia::Make();
216 auto atlas_context = context->CreateGlyphAtlasContext();
217 ASSERT_TRUE(context && context->IsValid());
218 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
219 auto blob = SkTextBlob::MakeFromString("spooky 1", sk_font);
220 ASSERT_TRUE(blob);
221 auto atlas = CreateGlyphAtlas(
222 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
223 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
224 auto old_packer = atlas_context->GetRectPacker();
225
226 ASSERT_NE(atlas, nullptr);
227 ASSERT_NE(atlas->GetTexture(), nullptr);
228 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
229
230 auto* first_texture = atlas->GetTexture().get();
231
232 // Now create a new glyph atlas with a nearly identical blob.
233
234 auto blob2 = SkTextBlob::MakeFromString("spooky 2", sk_font);
235 auto next_atlas = CreateGlyphAtlas(
236 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
237 atlas_context, *MakeTextFrameFromTextBlobSkia(blob2));
238 ASSERT_EQ(atlas, next_atlas);
239 auto* second_texture = next_atlas->GetTexture().get();
240
241 auto new_packer = atlas_context->GetRectPacker();
242
243 ASSERT_EQ(second_texture, first_texture);
244 ASSERT_EQ(old_packer, new_packer);
245 }

References CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [414/419]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasTextureIsRecycledWhenContentsAreNotRecreated |
| ) |  |

Definition at line 341 of file typographer_unittests.cc.

342 {
343 auto context = TypographerContextSkia::Make();
344 auto atlas_context = context->CreateGlyphAtlasContext();
345 ASSERT_TRUE(context && context->IsValid());
346 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
347 auto blob = SkTextBlob::MakeFromString("ABCDEFGHIJKLMNOPQRSTUVQXYZ123456789",
348 sk_font);
349 ASSERT_TRUE(blob);
350 auto atlas = CreateGlyphAtlas(
351 *GetContext(), context.get(), GlyphAtlas::Type::kColorBitmap, 32.0f,
352 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
353 auto old_packer = atlas_context->GetRectPacker();
354
355 ASSERT_NE(atlas, nullptr);
356 ASSERT_NE(atlas->GetTexture(), nullptr);
357 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
358
359 auto* first_texture = atlas->GetTexture().get();
360
361 // Now create a new glyph atlas with a completely different textblob.
362 // everything should be different except for the underlying atlas texture.
363
364 auto blob2 = SkTextBlob::MakeFromString("abcdefghijklmnopqrstuvwxyz123456789",
365 sk_font);
366 auto next_atlas = CreateGlyphAtlas(
367 *GetContext(), context.get(), GlyphAtlas::Type::kColorBitmap, 32.0f,
368 atlas_context, *MakeTextFrameFromTextBlobSkia(blob2));
369 ASSERT_NE(atlas, next_atlas);
370 auto* second_texture = next_atlas->GetTexture().get();
371
372 auto new_packer = atlas_context->GetRectPacker();
373
374 ASSERT_NE(second_texture, first_texture);
375 ASSERT_NE(old_packer, new_packer);
376 }

References CreateGlyphAtlas(), impeller::GlyphAtlas::kColorBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [415/419]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasWithLotsOfdUniqueGlyphSize |
| ) |  |

Definition at line 170 of file typographer_unittests.cc.

170 {
171 auto context = TypographerContextSkia::Make();
172 auto atlas_context = context->CreateGlyphAtlasContext();
173 ASSERT_TRUE(context && context->IsValid());
174
175 const char* test_string =
176 "QWERTYUIOPASDFGHJKLZXCVBNMqewrtyuiopasdfghjklzxcvbnm,.<>[]{};':"
177 "2134567890-=!@#$%^&*()_+"
178 "œ∑´®†¥¨ˆøπ““‘‘åß∂ƒ©˙∆˚¬…æ≈ç√∫˜µ≤≥≥≥≥÷¡™£¢∞§¶•ªº–≠⁄€‹›ﬁﬂ‡°·‚—±Œ„´‰Á¨Ø∏”’/"
179 "* Í˝ */¸˛Ç◊ı˜Â¯˘¿";
180
181 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
182 auto blob = SkTextBlob::MakeFromString(test_string, sk_font);
183 ASSERT_TRUE(blob);
184
185 FontGlyphMap font_glyph_map;
186 size_t size_count = 8;
187 for (size_t index = 0; index < size_count; index += 1) {
188 MakeTextFrameFromTextBlobSkia(blob)->CollectUniqueFontGlyphPairs(
189 font_glyph_map, 0.6 * index);
190 };
191 auto atlas =
192 context->CreateGlyphAtlas(*GetContext(), GlyphAtlas::Type::kAlphaBitmap,
193 atlas_context, font_glyph_map);
194 ASSERT_NE(atlas, nullptr);
195 ASSERT_NE(atlas->GetTexture(), nullptr);
196
197 std::set<uint16_t> unique_glyphs;
198 std::vector<uint16_t> total_glyphs;
199 atlas->IterateGlyphs(
200 [&](const ScaledFont& scaled_font, const Glyph& glyph, const Rect& rect) {
201 unique_glyphs.insert(glyph.index);
202 total_glyphs.push_back(glyph.index);
203 return true;
204 });
205
206 EXPECT_EQ(unique_glyphs.size() * size_count, atlas->GetGlyphCount());
207 EXPECT_EQ(total_glyphs.size(), atlas->GetGlyphCount());
208
209 EXPECT_TRUE(atlas->GetGlyphCount() > 0);
210 EXPECT_TRUE(atlas->GetTexture()->GetSize().width > 0);
211 EXPECT_TRUE(atlas->GetTexture()->GetSize().height > 0);
212 }

References impeller::Glyph::index, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [416/419]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasWithOddUniqueGlyphSize |
| ) |  |

Definition at line 130 of file typographer_unittests.cc.

130 {
131 auto context = TypographerContextSkia::Make();
132 auto atlas_context = context->CreateGlyphAtlasContext();
133 ASSERT_TRUE(context && context->IsValid());
134 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
135 auto blob = SkTextBlob::MakeFromString("AGH", sk_font);
136 ASSERT_TRUE(blob);
137 auto atlas = CreateGlyphAtlas(
138 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
139 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
140 ASSERT_NE(atlas, nullptr);
141 ASSERT_NE(atlas->GetTexture(), nullptr);
142
143 ASSERT_EQ(atlas->GetTexture()->GetSize().width,
144 atlas->GetTexture()->GetSize().height);
145 }

References CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [417/419]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | LazyAtlasTracksColor |
| ) |  |

Definition at line 92 of file typographer_unittests.cc.

92 {
93 #if FML_OS_MACOSX
94 auto mapping = flutter::testing::OpenFixtureAsSkData("Apple Color Emoji.ttc");
95 #else
96 auto mapping = flutter::testing::OpenFixtureAsSkData("NotoColorEmoji.ttf");
97 #endif
98 ASSERT_TRUE(mapping);
99 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
100 SkFont emoji_font(font_mgr->makeFromData(mapping), 50.0);
101 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
102
103 auto blob = SkTextBlob::MakeFromString("hello", sk_font);
104 ASSERT_TRUE(blob);
105 auto frame = MakeTextFrameFromTextBlobSkia(blob);
106
107 ASSERT_FALSE(frame->GetAtlasType() == GlyphAtlas::Type::kColorBitmap);
108
109 LazyGlyphAtlas lazy_atlas(TypographerContextSkia::Make());
110
111 lazy_atlas.AddTextFrame(*frame, 1.0f);
112
113 frame = MakeTextFrameFromTextBlobSkia(
114 SkTextBlob::MakeFromString("😀 ", emoji_font));
115
116 ASSERT_TRUE(frame->GetAtlasType() == GlyphAtlas::Type::kColorBitmap);
117
118 lazy_atlas.AddTextFrame(*frame, 1.0f);
119
120 // Creates different atlases for color and red bitmap.
121 auto color_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
122 *GetContext(), GlyphAtlas::Type::kColorBitmap);
123
124 auto bitmap_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
125 *GetContext(), GlyphAtlas::Type::kAlphaBitmap);
126
127 ASSERT_FALSE(color_atlas == bitmap_atlas);
128 }

References impeller::LazyGlyphAtlas::AddTextFrame(), impeller::LazyGlyphAtlas::CreateOrGetGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::GlyphAtlas::kColorBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [418/419]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | MaybeHasOverlapping |
| ) |  |

Definition at line 281 of file typographer_unittests.cc.

281 {
282 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
283 sk_sp<SkTypeface> typeface =
284 font_mgr->matchFamilyStyle("Arial", SkFontStyle::Normal());
285 SkFont sk_font(typeface, 0.5f);
286
287 auto frame =
288 MakeTextFrameFromTextBlobSkia(SkTextBlob::MakeFromString("1", sk_font));
289 // Single character has no overlapping
290 ASSERT_FALSE(frame->MaybeHasOverlapping());
291
292 auto frame_2 = MakeTextFrameFromTextBlobSkia(
293 SkTextBlob::MakeFromString("123456789", sk_font));
294 ASSERT_FALSE(frame_2->MaybeHasOverlapping());
295 }

References impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [419/419]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | RectanglePackerAddsNonoverlapingRectangles |
| ) |  |

Definition at line 297 of file typographer_unittests.cc.

297 {
298 auto packer = RectanglePacker::Factory(200, 100);
299 ASSERT_NE(packer, nullptr);
300 ASSERT_EQ(packer->percentFull(), 0);
301
302 const SkIRect packer_area = SkIRect::MakeXYWH(0, 0, 200, 100);
303
304 IPoint16 first_output = {-1, -1}; // Fill with sentinel values
305 ASSERT_TRUE(packer->addRect(20, 20, &first_output));
306 // Make sure the rectangle is placed such that it is inside the bounds of
307 // the packer's area.
308 const SkIRect first_rect =
309 SkIRect::MakeXYWH(first_output.x(), first_output.y(), 20, 20);
310 ASSERT_TRUE(SkIRect::Intersects(packer_area, first_rect));
311
312 // Initial area was 200 x 100 = 20_000
313 // We added 20x20 = 400. 400 / 20_000 == 0.02 == 2%
314 ASSERT_TRUE(flutter::testing::NumberNear(packer->percentFull(), 0.02));
315
316 IPoint16 second_output = {-1, -1};
317 ASSERT_TRUE(packer->addRect(140, 90, &second_output));
318 const SkIRect second_rect =
319 SkIRect::MakeXYWH(second_output.x(), second_output.y(), 140, 90);
320 // Make sure the rectangle is placed such that it is inside the bounds of
321 // the packer's area but not in the are of the first rectangle.
322 ASSERT_TRUE(SkIRect::Intersects(packer_area, second_rect));
323 ASSERT_FALSE(SkIRect::Intersects(first_rect, second_rect));
324
325 // We added another 90 x 140 = 12_600 units, now taking us to 13_000
326 // 13_000 / 20_000 == 0.65 == 65%
327 ASSERT_TRUE(flutter::testing::NumberNear(packer->percentFull(), 0.65));
328
329 // There's enough area to add this rectangle, but no space big enough for
330 // the 50 units of width.
331 IPoint16 output;
332 ASSERT_FALSE(packer->addRect(50, 50, &output));
333 // Should be unchanged.
334 ASSERT_TRUE(flutter::testing::NumberNear(packer->percentFull(), 0.65));
335
336 packer->reset();
337 // Should be empty now.
338 ASSERT_EQ(packer->percentFull(), 0);
339 }

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

## ◆ toColor()

flutter::DlColor impeller::testing::toColor | ( | const float * | components | ) |

Definition at line 41 of file dl_unittests.cc.

41 {
42 return flutter::DlColor(Color::ToIColor(
43 Color(components[0], components[1], components[2], components[3])));
44 }

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.

Referenced by TEST_P().

## ◆ kFontFixture

constexpr std::string_view impeller::testing::kFontFixture
| static constexpr

Initial value:
=
"NotoColorEmoji.ttf"

Definition at line 857 of file aiks_unittests.cc.

Referenced by TEST_P().

## ◆ kPaintVariations

const std::map<std::string, MaskBlurTestConfig> impeller::testing::kPaintVariations
| static

Definition at line 368 of file aiks_blur_unittests.cc.

_BLEND_MODE_RESULT_CHECK
#define _BLEND_MODE_RESULT_CHECK(blend_mode)
Definition: geometry_unittests.cc:1579
NumberNear
bool NumberNear(double a, double b)
Definition: geometry_asserts.h:18
ASSERT_COLOR_NEAR
#define ASSERT_COLOR_NEAR(a, b)
Definition: geometry_asserts.h:159
impeller::kFloat
@ kFloat
Definition: runtime_types.h:23
impeller::kResetTransform
@ kResetTransform
Definition: canvas_recorder.h:25
impeller::OptionsFromPass
ContentContextOptions OptionsFromPass(const RenderPass &pass)
Definition: contents.cc:20
impeller::k1OverSqrt2
constexpr float k1OverSqrt2
Definition: constants.h:50
impeller::kPreConcat
@ kPreConcat
Definition: canvas_recorder.h:28
impeller::kDrawImage
@ kDrawImage
Definition: canvas_recorder.h:42
impeller::testing::CompareFunctionUI
static const CompareFunctionUIData & CompareFunctionUI()
Definition: renderer_unittests.cc:1111
impeller::MyMask
Mask< MyMaskBits > MyMask
Definition: base_unittests.cc:20
impeller::BlendModeToString
const char * BlendModeToString(BlendMode blend_mode)
Definition: color.cc:47
impeller::kClipPath
@ kClipPath
Definition: canvas_recorder.h:44
polyline
const Path::Polyline & polyline
Definition: stroke_path_geometry.cc:292
impeller::kClipOval
@ kClipOval
Definition: canvas_recorder.h:46
impeller::TPoint::y
Type y
Definition: point.h:31
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::TPoint::Ceil
constexpr TPoint Ceil() const
Definition: point.h:196
impeller::testing::CompareFunctionUIData::IndexOf
int IndexOf(CompareFunction func) const
Definition: renderer_unittests.cc:1094
impeller::testing::CanRenderSweepGradientWithDithering
static void CanRenderSweepGradientWithDithering(AiksTest *aiks_test, bool use_dithering)
Definition: aiks_gradient_unittests.cc:137
impeller::kConcat
@ kConcat
Definition: canvas_recorder.h:27
impeller::skia_conversions::ConvertStops
void ConvertStops(const flutter::DlGradientColorSourceBase *gradient, std::vector< Color > &colors, std::vector< float > &stops)
Convert display list colors + stops into impeller colors and stops, taking care to ensure that the st...
Definition: skia_conversions.cc:198
impeller::testing::swap_nan
static constexpr Point swap_nan(const Point &point, int index)
Definition: rect_unittests.cc:1305
impeller::skia_conversions::ToSize
Size ToSize(const SkPoint &point)
Definition: skia_conversions.cc:144
impeller::BlendMode
BlendMode
Definition: color.h:59
impeller::testing::CreateMappingFromString
static std::shared_ptr< fml::Mapping > CreateMappingFromString(std::string p_string)
Definition: shader_archive_unittests.cc:20
impeller::TPoint::Lerp
constexpr TPoint Lerp(const TPoint &p, Scalar t) const
Definition: point.h:230
impeller::kEhCloseEnough
constexpr float kEhCloseEnough
Definition: constants.h:56
impeller::TextureDescriptor::format
PixelFormat format
Definition: texture_descriptor.h:40
impeller::testing::CanRenderConicalGradientWithDithering
static void CanRenderConicalGradientWithDithering(AiksTest *aiks_test, bool use_dithering)
Definition: aiks_gradient_unittests.cc:166
EXPECT_SOLID_VERTICES_NEAR
#define EXPECT_SOLID_VERTICES_NEAR(a, b)
Definition: geometry_unittests.cc:45
impeller::TPoint::Min
constexpr TPoint Min(const TPoint &p) const
Definition: point.h:186
impeller::kRotate
@ kRotate
Definition: canvas_recorder.h:33
impeller::TPoint::Round
static constexpr TPoint Round(const TPoint< U > &other)
Definition: point.h:49
impeller::Vector2
Point Vector2
Definition: point.h:320
EXPECT_POINT_NEAR
#define EXPECT_POINT_NEAR(a, b)
Definition: geometry_asserts.h:172
MatrixNear
inline ::testing::AssertionResult MatrixNear(impeller::Matrix a, impeller::Matrix b)
Definition: geometry_asserts.h:23
impeller::kPi
constexpr float kPi
Definition: constants.h:26
BLEND_MODE_TUPLE
#define BLEND_MODE_TUPLE(blend_mode)
Definition: aiks_unittests.cc:1033
impeller::testing::flip_lrtb
static constexpr R flip_lrtb(R rect)
Definition: rect_unittests.cc:1291
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::skia_conversions::ToColor
Color ToColor(const flutter::DlColor &color)
Definition: skia_conversions.cc:148
impeller::FontGlyphMap
std::unordered_map< ScaledFont, std::unordered_set< Glyph > > FontGlyphMap
Definition: font_glyph_pair.h:29
impeller::UintPoint32
TPoint< uint32_t > UintPoint32
Definition: point.h:319
impeller::testing::golden_cubic_and_quad_points
std::vector< Point > golden_cubic_and_quad_points
Definition: golden_paths.h:16
impeller::Size
TSize< Scalar > Size
Definition: size.h:137
impeller::StorageMode::kHostVisible
@ kHostVisible
ASSERT_POINT_NEAR
#define ASSERT_POINT_NEAR(a, b)
Definition: geometry_asserts.h:160
impeller::GenerateBlurInfo
KernelPipeline::FragmentShader::KernelSamples GenerateBlurInfo(BlurParameters parameters)
Definition: gaussian_blur_filter_contents.cc:586
impeller::CreateMappingFromAllocation
std::shared_ptr< fml::Mapping > CreateMappingFromAllocation(const std::shared_ptr< Allocation > &allocation)
Definition: allocation.cc:99
ASSERT_VECTOR4_NEAR
#define ASSERT_VECTOR4_NEAR(a, b)
Definition: geometry_asserts.h:162
impeller::PlaygroundBackendToRuntimeStageBackend
constexpr RuntimeStageBackend PlaygroundBackendToRuntimeStageBackend(PlaygroundBackend backend)
Definition: playground.h:35
impeller::kSave
@ kSave
Definition: canvas_recorder.h:21
stroke_width
const Scalar stroke_width
Definition: stroke_path_geometry.cc:293
impeller::MoveTo
void MoveTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:18
EXPECT_RECT_NEAR
#define EXPECT_RECT_NEAR(a, b)
Definition: geometry_asserts.h:170
impeller::GetDrawableDeferred
std::shared_future< id< CAMetalDrawable > > GetDrawableDeferred(CAMetalLayer *layer)
Create a deferred drawable from a CAMetalLayer.
Definition: lazy_drawable_holder.mm:23
impeller::TPoint::Floor
constexpr TPoint Floor() const
Definition: point.h:194
impeller::ToShaderStage
constexpr ShaderStage ToShaderStage(RuntimeShaderStage stage)
Definition: shader_types.h:29
impeller::testing::RenderTextInCanvasSTB
bool RenderTextInCanvasSTB(const std::shared_ptr< Context > &context, Canvas &canvas, const std::string &text, const std::string &font_fixture, TextRenderOptions options={})
Definition: aiks_unittests.cc:751
impeller::kPiOver2
constexpr float kPiOver2
Definition: constants.h:32
impeller::LerpHackKernelSamples
KernelPipeline::FragmentShader::KernelSamples LerpHackKernelSamples(KernelPipeline::FragmentShader::KernelSamples parameters)
Definition: gaussian_blur_filter_contents.cc:622
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:100
ASSERT_RECT_NEAR
#define ASSERT_RECT_NEAR(a, b)
Definition: geometry_asserts.h:158
impeller::MakeTextFrameSTB
std::shared_ptr< TextFrame > MakeTextFrameSTB(const std::shared_ptr< TypefaceSTB > &typeface_stb, Font::Metrics metrics, const std::string &text)
Definition: text_frame_stb.cc:11
impeller::kDrawCircle
@ kDrawCircle
Definition: canvas_recorder.h:40
impeller::kPhi
constexpr float kPhi
Definition: constants.h:53
impeller::VS
SolidFillVertexShader VS
Definition: stroke_path_geometry.cc:15
impeller::kColor
@ kColor
Definition: geometry.h:51
impeller::saturated::distance
SI distance
Definition: saturated_math.h:57
impeller::testing::toColor
flutter::DlColor toColor(const float *components)
Definition: dl_unittests.cc:41
impeller::kDrawTextFrame
@ kDrawTextFrame
Definition: canvas_recorder.h:48
impeller::testing::CreateColorVertices
std::shared_ptr< VerticesGeometry > CreateColorVertices(const std::vector< Point > &vertices, const std::vector< Color > &colors)
Definition: vertices_contents_unittests.cc:26
impeller::kScale2
@ kScale2
Definition: canvas_recorder.h:30
impeller::Point
TPoint< Scalar > Point
Definition: point.h:316
impeller::k2Pi
constexpr float k2Pi
Definition: constants.h:29
impeller::Quad
std::array< Point, 4 > Quad
Definition: point.h:321
impeller::testing::CompareFunctionUIData::FunctionOf
CompareFunction FunctionOf(int index) const
Definition: renderer_unittests.cc:1104
impeller::testing::RGBToYUV
static Vector3 RGBToYUV(Vector3 rgb, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:2093
impeller::MipFilter
MipFilter
Definition: formats.h:415
impeller::testing::flip_lr
static constexpr R flip_lr(R rect)
Definition: rect_unittests.cc:1279
impeller::SPrintF
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
impeller::testing::GetBlendModeSelection
static BlendModeSelection GetBlendModeSelection()
Definition: aiks_unittests.cc:1040
impeller::IPoint32
TPoint< int32_t > IPoint32
Definition: point.h:318
impeller::ScalarToHalf
constexpr InternalHalf ScalarToHalf(Scalar f)
Convert a scalar to a half precision float.
Definition: half.h:32
EXPECT_TEXTURE_VERTICES_NEAR
#define EXPECT_TEXTURE_VERTICES_NEAR(a, b)
Definition: geometry_unittests.cc:47
impeller::kDrawRect
@ kDrawRect
Definition: canvas_recorder.h:37
impeller::TPoint::Max
constexpr TPoint Max(const TPoint &p) const
Definition: point.h:190
impeller::testing::CreatePassWithRectPath
auto CreatePassWithRectPath(Rect rect, std::optional< Rect > bounds_hint, ContentBoundsPromise bounds_promise=ContentBoundsPromise::kUnknown, bool collapse=false)
Definition: entity_unittests.cc:109
impeller::testing::CanRenderRadialGradientWithDithering
static void CanRenderRadialGradientWithDithering(AiksTest *aiks_test, bool use_dithering)
Definition: aiks_gradient_unittests.cc:110
impeller::kSkew
@ kSkew
Definition: canvas_recorder.h:32
impeller::kClipRRect
@ kClipRRect
Definition: canvas_recorder.h:47
impeller::MinMagFilter
MinMagFilter
Definition: formats.h:407
impeller::kDrawImageRect
@ kDrawImageRect
Definition: canvas_recorder.h:43
impeller::testing::CanRenderLinearGradientWithDithering
static void CanRenderLinearGradientWithDithering(AiksTest *aiks_test, bool use_dithering)
Definition: aiks_gradient_unittests.cc:82
impeller::testing::CreateTestYUVTextures
static std::vector< std::shared_ptr< Texture > > CreateTestYUVTextures(Context *context, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:2110
_BLEND_MODE_NAME_CHECK
#define _BLEND_MODE_NAME_CHECK(blend_mode)
Definition: geometry_unittests.cc:1598
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:661
ASSERT_MATRIX_NEAR
#define ASSERT_MATRIX_NEAR(a, b)
Definition: geometry_asserts.h:156
impeller::testing::CreateStringFromMapping
const std::string CreateStringFromMapping(const fml::Mapping &mapping)
Definition: shader_archive_unittests.cc:28
impeller::TextureUsageMask
Mask< TextureUsage > TextureUsageMask
Definition: formats.h:309
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
impeller::kStruct
@ kStruct
Definition: runtime_types.h:25
impeller::kTransform
@ kTransform
Definition: canvas_recorder.h:26
impeller::kDrawAtlas
@ kDrawAtlas
Definition: canvas_recorder.h:50
impeller::skia_conversions::ToPoint
Point ToPoint(const SkPoint &point)
Definition: skia_conversions.cc:140
IMPELLER_FOR_EACH_BLEND_MODE
#define IMPELLER_FOR_EACH_BLEND_MODE(V)
Definition: color.h:19
IMPELLER_RAND
#define IMPELLER_RAND
Definition: gaussian_blur_filter_contents_unittests.cc:17
impeller::IRect
TRect< int64_t > IRect
Definition: rect.h:662
impeller::MakeTextFrameFromTextBlobSkia
std::shared_ptr< TextFrame > MakeTextFrameFromTextBlobSkia(const sk_sp< SkTextBlob > &blob)
Definition: text_frame_skia.cc:41
impeller::kDrawPaint
@ kDrawPaint
Definition: canvas_recorder.h:35
impeller::ToMTLPixelFormat
constexpr MTLPixelFormat ToMTLPixelFormat(PixelFormat format)
Definition: formats_mtl.h:77
ASSERT_QUATERNION_NEAR
#define ASSERT_QUATERNION_NEAR(a, b)
Definition: geometry_asserts.h:157
impeller::Close
void Close(PathBuilder *builder)
Definition: tessellator.cc:36
impeller::ISize
TSize< int64_t > ISize
Definition: size.h:138
impeller::kSaveLayer
@ kSaveLayer
Definition: canvas_recorder.h:22
impeller::TextureDescriptor::size
ISize size
Definition: texture_descriptor.h:41
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:73
impeller::testing::RenderTextInCanvasSkia
bool RenderTextInCanvasSkia(const std::shared_ptr< Context > &context, Canvas &canvas, const std::string &text, const std::string_view &font_fixture, TextRenderOptions options={})
Definition: aiks_unittests.cc:714
impeller::LineTo
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:22
impeller::Join
Join
Definition: path.h:23
textures
std::vector< std::shared_ptr< FakeTexture > > textures
Definition: content_context_unittests.cc:92
RectNear
inline ::testing::AssertionResult RectNear(impeller::Rect a, impeller::Rect b)
Definition: geometry_asserts.h:56
impeller::DrawPlaygroundPoint
Point DrawPlaygroundPoint(PlaygroundPoint &point)
Definition: widgets.cc:9
impeller::kDrawPoints
@ kDrawPoints
Definition: canvas_recorder.h:41
impeller::IPoint
TPoint< int64_t > IPoint
Definition: point.h:317
impeller::MyMaskBits
MyMaskBits
Definition: base_unittests.cc:13
ASSERT_VECTOR3_NEAR
#define ASSERT_VECTOR3_NEAR(a, b)
Definition: geometry_asserts.h:161
FLT_FORWARD
#define FLT_FORWARD(mock, real, method)
Definition: aiks_blur_unittests.cc:489
impeller::saturated::b
SI b
Definition: saturated_math.h:87
impeller::testing::kFontFixture
static constexpr std::string_view kFontFixture
Definition: aiks_unittests.cc:857
scale
const Scalar scale
Definition: stroke_path_geometry.cc:297
impeller::ScalarNearlyEqual
constexpr bool ScalarNearlyEqual(Scalar x, Scalar y, Scalar tolerance=kEhCloseEnough)
Definition: scalar.h:30
impeller::YUVColorSpace
YUVColorSpace
Definition: color.h:55
impeller::kDrawOval
@ kDrawOval
Definition: canvas_recorder.h:38
impeller::SampleCount::kCount1
@ kCount1
impeller::TextureDescriptor::storage_mode
StorageMode storage_mode
Definition: texture_descriptor.h:38
impeller::kScale3
@ kScale3
Definition: canvas_recorder.h:31
impeller::TPoint::GetDistance
constexpr Type GetDistance(const TPoint &p) const
Definition: point.h:200
impeller::TextureDescriptor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
Definition: texture_descriptor.h:37
offset
Point offset
Definition: stroke_path_geometry.cc:300
impeller::testing::CreateGlyphAtlas
static std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, const TypographerContext *typographer_context, GlyphAtlas::Type type, Scalar scale, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const TextFrame &frame)
Definition: typographer_unittests.cc:28
impeller::TSize::MipCount
constexpr size_t MipCount() const
Definition: size.h:115
impeller::kDrawVertices
@ kDrawVertices
Definition: canvas_recorder.h:49
impeller::TPoint::Normalize
constexpr TPoint Normalize() const
Definition: point.h:208
impeller::kDrawLine
@ kDrawLine
Definition: canvas_recorder.h:36
impeller::testing::flip_tb
static constexpr R flip_tb(R rect)
Definition: rect_unittests.cc:1285
impeller::kDrawPath
@ kDrawPath
Definition: canvas_recorder.h:34
impeller::kDrawRRect
@ kDrawRRect
Definition: canvas_recorder.h:39
ASSERT_COLOR_BUFFER_NEAR
#define ASSERT_COLOR_BUFFER_NEAR(a, b)
Definition: geometry_asserts.h:165
impeller::kRestore
@ kRestore
Definition: canvas_recorder.h:23
impeller::kPiOver4
constexpr float kPiOver4
Definition: constants.h:35
impeller::skia_conversions::ToPath
Path ToPath(const SkPath &path, Point shift)
Definition: skia_conversions.cc:49
impeller::kTranslate
@ kTranslate
Definition: canvas_recorder.h:29
impeller::kClipRect
@ kClipRect
Definition: canvas_recorder.h:45
impeller::Cap
Cap
Definition: path.h:17
ASSERT_ARRAY_4_NEAR
#define ASSERT_ARRAY_4_NEAR(a, b)
Definition: geometry_asserts.h:164
IPLR_REQUIRES
#define IPLR_REQUIRES(...)
Definition: thread_safety.h:30
impeller::DrawPlaygroundLine
std::tuple< Point, Point > DrawPlaygroundLine(PlaygroundPoint &point_a, PlaygroundPoint &point_b)
Definition: widgets.cc:50
impeller::kRestoreToCount
@ kRestoreToCount
Definition: canvas_recorder.h:24