| Flutter Impeller |

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

## Classes
class | ArchivistFixture
struct | BlendModeSelection
class | CompareFunctionUIData
struct | CVTest
class | DirectionalGaussianBlurFilterContentsTest
struct | Foo
class | GaussianBlurFilterContentsTest
class | GoldenDigest
| Manages a global variable for tracking instances of golden images. More...
class | GoldenTests
class | MetalScreenshot
| A screenshot that was produced from `MetalScreenshotter`. More...
class | MetalScreenshotter
class | RendererDartTest
struct | RWFoo
class | Sample
class | SampleWithVector
class | TestAllocator
class | TestPassDelegate
class | TestRenderTargetAllocator
struct | TextRenderOptions
class | WorkingDirectory

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

## Functions
| 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)
| 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, CanRenderTiledTextureClamp)
| TEST_P (AiksTest, CanRenderTiledTextureClampAsync)
| 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, 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 (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, CanRenderMaskBlurHugeSigma)
| TEST_P (AiksTest, CanRenderBackdropBlurInteractive)
| TEST_P (AiksTest, CanRenderBackdropBlur)
| TEST_P (AiksTest, CanRenderBackdropBlurHugeSigma)
| TEST_P (AiksTest, CanRenderClippedBlur)
| TEST_P (AiksTest, CanRenderForegroundBlendWithMaskBlur)
| TEST_P (AiksTest, CanRenderForegroundAdvancedBlendWithMaskBlur)
| 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, CanCanvasDrawPicture)
| TEST_P (AiksTest, CanCanvasDrawPictureWithAdvancedBlend)
| TEST_P (AiksTest, CanCanvasDrawPictureWithBackdropFilter)
| TEST_P (AiksTest, DrawPictureWithText)
| TEST_P (AiksTest, DrawPictureClipped)
| 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, ClippedBlurFilterRendersCorrectlyInteractive)
| TEST_P (AiksTest, ClippedBlurFilterRendersCorrectly)
| TEST_P (AiksTest, CaptureContext)
| TEST_P (AiksTest, CaptureInactivatedByDefault)
| TEST_P (AiksTest, ReleasesTextureOnTeardown)
| TEST_P (AiksTest, VerticesGeometryUVPositionData)
| TEST_P (AiksTest, VerticesGeometryUVPositionDataWithTranslate)
| TEST_P (AiksTest, ClearBlendWithBlur)
| TEST_P (AiksTest, ClearBlend)
| TEST_P (AiksTest, MatrixImageFilterMagnify)
| TEST_P (AiksTest, MatrixImageFilterDoesntCullWhenTranslatedFromOffscreen)
| TEST_P (AiksTest, MatrixImageFilterDoesntCullWhenScaledAndTranslatedFromOffscreen)
| TEST_P (AiksTest, ClearColorOptimizationWhenSubpassIsBiggerThanParentPass)
| TEST_P (AiksTest, BlurHasNoEdge)
| TEST_P (AiksTest, EmptySaveLayerIgnoresPaint)
| TEST_P (AiksTest, EmptySaveLayerRendersWithClear)
| TEST_P (AiksTest, BlurredRectangleWithShader)
| TEST_P (AiksTest, MaskBlurWithZeroSigmaIsSkipped)
| 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, SubpassWithClearColorOptimization)
| 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, DrawRect)
| TEST (CanvasRecorder, DrawRRect)
| TEST (CanvasRecorder, DrawCircle)
| TEST (CanvasRecorder, DrawPoints)
| TEST (CanvasRecorder, DrawImage)
| TEST (CanvasRecorder, DrawImageRect)
| TEST (CanvasRecorder, ClipPath)
| TEST (CanvasRecorder, ClipRect)
| TEST (CanvasRecorder, ClipRRect)
| TEST (CanvasRecorder, DrawPicture)
| 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_F (ArchiveTest, SimpleInitialization)
| TEST_F (ArchiveTest, AddStorageClass)
| TEST_F (ArchiveTest, AddData)
| TEST_F (ArchiveTest, AddDataMultiple)
| TEST_F (ArchiveTest, ReadData)
| TEST_F (ArchiveTest, ReadDataWithNames)
| TEST_F (ArchiveTest, CanReadWriteVectorOfArchivables)
| 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 (AllocatorTest, TextureDescriptorCompatibility)
flutter::DlColor | toColor (const float *components)
| INSTANTIATE_PLAYGROUND_SUITE (DisplayListTest)
| TEST_P (DisplayListTest, DrawPictureWithAClip)
| 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, 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 (SkiaConversionsTest, SkPointToPoint)
| TEST (SkiaConversionsTest, SkPointToSize)
| TEST (SkiaConversionsTest, ToColor)
| TEST (SkiaConversionsTest, GradientStopConversion)
| TEST (SkiaConversionsTest, GradientMissing0)
| TEST (SkiaConversionsTest, GradientMissingLastValue)
| TEST (SkiaConversionsTest, GradientStopGreaterThan1)
| TEST (SkiaConversionsTest, GradientConversionNonMonotonic)
| INSTANTIATE_PLAYGROUND_SUITE (DirectionalGaussianBlurFilterContentsTest)
| TEST_P (DirectionalGaussianBlurFilterContentsTest, CoverageWithEffectTransform)
| TEST (DirectionalGaussianBlurFilterContentsTest, FilterSourceCoverage)
| TEST_P (DirectionalGaussianBlurFilterContentsTest, RenderNoCoverage)
| TEST_P (DirectionalGaussianBlurFilterContentsTest, RenderCoverageMatchesGetCoverage)
| TEST_P (DirectionalGaussianBlurFilterContentsTest, TextureContentsWithDestinationRect)
| TEST_P (DirectionalGaussianBlurFilterContentsTest, TextureContentsWithDestinationRectScaled)
| 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 (GaussianBlurFilterContentsTest, CalculateSigmaForBlurRadius)
| TEST (GaussianBlurFilterContentsTest, Coefficients)
| TEST (FilterInputTest, CanSetLocalTransformForTexture)
| TEST (FilterInputTest, IsLeaf)
| TEST (FilterInputTest, SetCoverageInputs)
| 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)
| INSTANTIATE_PLAYGROUND_SUITE (EntityPassTargetTest)
| TEST_P (EntityPassTargetTest, SwapWithMSAATexture)
| TEST_P (EntityPassTargetTest, SwapWithMSAAImplicitResolve)
| TEST_P (EntityTest, CanCreateEntity)
auto | CreatePassWithRectPath (Rect rect, std::optional< Rect > bounds_hint, bool collapse=false)
| TEST_P (EntityTest, EntityPassRespectsSubpassBoundsLimit)
| 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, 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, PointFieldCanUseCompute)
| TEST_P (EntityTest, ColorFilterContentsWithLargeGeometry)
| TEST_P (EntityTest, TextContentsCeilsGlyphScaleToDecimal)
| TEST_P (EntityTest, AdvancedBlendCoverageHintIsNotResetByEntityPass)
| TEST_P (EntityTest, SpecializationConstantsAreAppliedToVariants)
| TEST_P (EntityTest, DecalSpecializationAppliedToMorphologyFilter)
| TEST_P (EntityTest, FramebufferFetchPipelinesDeclareUsage)
| TEST_P (EntityTest, PipelineDescriptorEqAndHash)
| TEST_P (EntityTest, ContentContextOptionsHasReasonableHashFunctions)
| TEST (EntityGeometryTest, RectGeometryCoversArea)
| TEST (EntityGeometryTest, FillPathGeometryCoversArea)
| TEST (EntityGeometryTest, FillPathGeometryCoversAreaNoInnerRect)
| TEST (EntityGeometryTest, LineGeometryCoverage)
| TEST (EntityGeometryTest, RoundRectGeometryCoversArea)
| TEST (RenderTargetCacheTest, CachesUsedTexturesAcrossFrames)
| TEST (RenderTargetCacheTest, DoesNotPersistFailedAllocations)
| 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, BlendModeToString)
| TEST (GeometryTest, CanConvertBetweenDegressAndRadians)
| TEST (GeometryTest, RectUnion)
| TEST (GeometryTest, OptRectUnion)
| TEST (GeometryTest, RectIntersection)
| TEST (GeometryTest, OptRectIntersection)
| TEST (GeometryTest, RectIntersectsWithRect)
| TEST (GeometryTest, RectCutout)
| TEST (GeometryTest, RectContainsPoint)
| TEST (GeometryTest, RectContainsRect)
| TEST (GeometryTest, RectGetPoints)
| TEST (GeometryTest, RectShift)
| TEST (GeometryTest, RectGetTransformedPoints)
| TEST (GeometryTest, RectMakePointBounds)
| TEST (GeometryTest, RectExpand)
| TEST (GeometryTest, RectGetPositive)
| TEST (GeometryTest, RectScale)
| TEST (GeometryTest, RectDirections)
| TEST (GeometryTest, RectProject)
| TEST (GeometryTest, RectRoundOut)
| 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 (RectTest, RectOriginSizeXYWHGetters)
| TEST (RectTest, IRectOriginSizeXYWHGetters)
| TEST (RectTest, RectFromRect)
| TEST (RectTest, RectFromIRect)
| TEST (RectTest, IRectFromRect)
| TEST (RectTest, IRectFromIRect)
| TEST (RectTest, RectMakeSize)
| TEST (RectTest, RectScale)
| TEST (RectTest, IRectScale)
| TEST (RectTest, RectArea)
| TEST (RectTest, IRectArea)
| TEST (RectTest, RectGetNormalizingTransform)
| TEST (RectTest, IRectGetNormalizingTransform)
| TEST (SizeTest, RectIsEmpty)
| TEST (SizeTest, IRectIsEmpty)
| TEST (RectTest, MakePointBoundsQuad)
| TEST (RectTest, IsSquare)
| TEST (RectTest, GetCenter)
| TEST (RectTest, RectExpand)
| TEST (RectTest, IRectExpand)
| TEST (RectTest, ContainsFloatingPoint)
| 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 (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 (ContextVKTest, DeletesCommandPools)
| TEST (ContextVKTest, DeletesCommandPoolsOnAllThreads)
| TEST (ContextVKTest, DeletePipelineAfterContext)
| TEST (ContextVKTest, DeleteShaderFunctionAfterContext)
| TEST (ContextVKTest, DeletePipelineLibraryAfterContext)
| TEST (ContextVKTest, CanCreateContextInAbsenceOfValidationLayers)
| TEST (ContextVKTest, CanCreateContextWithValidationLayers)
| TEST (DescriptorPoolRecyclerVKTest, GetDescriptorPoolRecyclerCreatesNewPools)
| TEST (DescriptorPoolRecyclerVKTest, DescriptorPoolCapacityIsRoundedUp)
| TEST (DescriptorPoolRecyclerVKTest, ReclaimMakesDescriptorPoolAvailable)
| TEST (DescriptorPoolRecyclerVKTest, ReclaimDropsDescriptorPoolIfSizeIsExceeded)
| TEST (FenceWaiterVKTest, IgnoresNullFence)
| TEST (FenceWaiterVKTest, IgnoresNullCallback)
| TEST (FenceWaiterVKTest, ExecutesFenceCallback)
| TEST (FenceWaiterVKTest, ExecutesFenceCallbackX2)
| TEST (FenceWaiterVKTest, ExecutesNewFenceThenOldFence)
| TEST (FenceWaiterVKTest, AddFenceDoesNothingIfTerminating)
| TEST (FenceWaiterVKTest, InProgressFencesStillWaitIfTerminated)
| TEST (PassBindingsCacheTest, bindPipeline)
| TEST (PassBindingsCacheTest, setStencilReference)
| TEST (PassBindingsCacheTest, setScissor)
| TEST (PassBindingsCacheTest, setViewport)
| 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)
| 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 (HostBufferTest, TestInitialization)
| TEST (HostBufferTest, CanEmplace)
| TEST (HostBufferTest, CanEmplaceWithAlignment)
| TEST (PipelineDescriptorTest, PrimitiveTypeHashEquality)
| TEST (PoolTest, Simple)
| TEST (PoolTest, Overload)
static void | InstantiateTestShaderLibrary ()
| INSTANTIATE_PLAYGROUND_SUITE (RendererDartTest)
| TEST_P (RendererDartTest, CanRunDartInPlaygroundFrame)
| TEST_P (RendererDartTest, CanInstantiateFlutterGPUContext)
| DART_TEST_CASE (canEmplaceHostBuffer)
| DART_TEST_CASE (canCreateDeviceBuffer)
| DART_TEST_CASE (canOverwriteDeviceBuffer)
| DART_TEST_CASE (deviceBufferOverwriteFailsWhenOutOfBounds)
| DART_TEST_CASE (deviceBufferOverwriteThrowsForNegativeDestinationOffset)
| DART_TEST_CASE (canCreateTexture)
| DART_TEST_CASE (canOverwriteTexture)
| DART_TEST_CASE (textureOverwriteThrowsForWrongBufferSize)
| DART_TEST_CASE (textureAsImageReturnsAValidUIImageHandle)
| DART_TEST_CASE (textureAsImageThrowsWhenNotShaderReadable)
| DART_TEST_CASE (canCreateShaderLibrary)
| 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, CanPreAllocateCommands)
| TEST_P (RendererTest, CanLookupRenderTargetProperties)
| 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)
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, GlyphAtlasTextureIsRecycledWhenContentsAreRecreated)

## Variables
static constexpr std::string_view | kFontFixture
static int64_t | LastSample = 0
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.

## ◆ ArchiveTest

using impeller::testing::ArchiveTest = typedef ArchivistFixture

Definition at line 110 of file archivist_unittests.cc.

## ◆ 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 26 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.

## ◆ EntityPassTargetTest

using impeller::testing::EntityPassTargetTest = typedef EntityPlayground

Definition at line 16 of file entity_pass_target_unittests.cc.

## ◆ EntityTest

typedef EntityPlayground impeller::testing::EntityTest

Definition at line 19 of file checkerboard_contents_unittests.cc.

## ◆ RendererTest

using impeller::testing::RendererTest = typedef PlaygroundTest

Definition at line 43 of file renderer_unittests.cc.

## ◆ RuntimeStageTest

using impeller::testing::RuntimeStageTest = typedef RuntimeStagePlayground

Definition at line 24 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 | ( | 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 (top right).

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

Definition at line 2196 of file aiks_unittests.cc.

2198 {
2199 Color destination_color = Color::CornflowerBlue().WithAlpha(0.75);
2200 auto source_colors = std::vector<Color>({Color::White().WithAlpha(0.75),
2201 Color::LimeGreen().WithAlpha(0.75),
2202 Color::Black().WithAlpha(0.75)});
2203
2204 Canvas canvas;
2205
2206 canvas.DrawPaint({.color = Color::Black()});
2207
2208 //----------------------------------------------------------------------------
2209 /// 1. Save layer blending (top squares).
2210 ///
2211
2212 canvas.Save();
2213 for (const auto& color : source_colors) {
2214 canvas.Save();
2215 {
2216 canvas.ClipRect(Rect::MakeXYWH(50, 50, 100, 100));
2217 // Perform the blend in a SaveLayer so that the initial backdrop color is
2218 // fully transparent black. SourceOver blend the result onto the parent
2219 // pass.
2220 canvas.SaveLayer({});
2221 {
2222 canvas.DrawPaint({.color = destination_color});
2223 // Draw the source color in an offscreen pass and blend it to the parent
2224 // pass.
2225 canvas.SaveLayer({.blend_mode = blend_mode});
2226 { //
2227 canvas.DrawRect(Rect::MakeXYWH(50, 50, 100, 100), {.color = color});
2228 }
2229 canvas.Restore();
2230 }
2231 canvas.Restore();
2232 }
2233 canvas.Restore();
2234 canvas.Translate(Vector2(100, 0));
2235 }
2236 canvas.RestoreToCount(0);
2237
2238 //----------------------------------------------------------------------------
2239 /// 2. CPU blend modes (bottom squares).
2240 ///
2241
2242 canvas.Save();
2243 canvas.Translate({0, 100});
2244
2245 // Perform the blend in a SaveLayer so that the initial backdrop color is
2246 // fully transparent black. SourceOver blend the result onto the parent pass.
2247 canvas.SaveLayer({});
2248 // canvas.DrawPaint({.color = destination_color});
2249 for (const auto& color : source_colors) {
2250 // Simply write the CPU blended color to the pass.
2251 canvas.DrawRect(Rect::MakeXYWH(50, 50, 100, 100),
2252 {.color = destination_color.Blend(color, blend_mode),
2253 .blend_mode = BlendMode::kSourceOver});
2254 canvas.Translate(Vector2(100, 0));
2255 }
2256 canvas.RestoreToCount(0);
2257
2258 //----------------------------------------------------------------------------
2259 /// 3. Image blending (top right).
2260 ///
2261 /// Compare these results with the images in the Flutter blend mode
2262 /// documentation: https://api.flutter.dev/flutter/dart-ui/BlendMode.html
2263 ///
2264
2265 canvas.Save();
2266 // canvas.ClipRect(Rect::MakeXYWH(500, 0, 500, 500));
2267 canvas.SaveLayer({.blend_mode = BlendMode::kSourceOver});
2268 {
2269 canvas.DrawImage(dst_image, {400, 50}, {.blend_mode = BlendMode::kSource});
2270 canvas.DrawImage(src_image, {400, 50}, {.blend_mode = blend_mode});
2271 }
2272 canvas.RestoreToCount(0);
2273
2274 return canvas.EndRecordingAsPicture();
2275 }

References impeller::Color::Black(), impeller::Color::Blend(), impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::kSource, impeller::kSourceOver, impeller::Color::LimeGreen(), 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 169 of file aiks_gradient_unittests.cc.

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

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 85 of file aiks_gradient_unittests.cc.

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

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 113 of file aiks_gradient_unittests.cc.

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

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 140 of file aiks_gradient_unittests.cc.

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

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

1109 {
1110 static CompareFunctionUIData data;
1111 return data;
1112 }

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 25 of file vertices_contents_unittests.cc.

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

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

Referenced by TEST_P().

## ◆ 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(), and impeller::TypographerContext::CreateGlyphAtlas().

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,
|  | bool | collapse = `false`
| ) |  |

Definition at line 105 of file entity_unittests.cc.

107 {
108 auto subpass = std::make_unique<EntityPass>();
109 Entity entity;
110 entity.SetContents(SolidColorContents::Make(
111 PathBuilder{}.AddRect(rect).TakePath(), Color::Red()));
112 subpass->AddEntity(std::move(entity));
113 subpass->SetDelegate(std::make_unique<TestPassDelegate>(collapse));
114 subpass->SetBoundsLimit(bounds_hint);
115 return subpass;
116 }

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

2052 {
2053 Vector3 red = {244.0 / 255.0, 67.0 / 255.0, 54.0 / 255.0};
2054 Vector3 green = {76.0 / 255.0, 175.0 / 255.0, 80.0 / 255.0};
2055 Vector3 blue = {33.0 / 255.0, 150.0 / 255.0, 243.0 / 255.0};
2056 Vector3 white = {1.0, 1.0, 1.0};
2057 Vector3 red_yuv = RGBToYUV(red, yuv_color_space);
2058 Vector3 green_yuv = RGBToYUV(green, yuv_color_space);
2059 Vector3 blue_yuv = RGBToYUV(blue, yuv_color_space);
2060 Vector3 white_yuv = RGBToYUV(white, yuv_color_space);
2061 std::vector<Vector3> yuvs{red_yuv, green_yuv, blue_yuv, white_yuv};
2062 std::vector<uint8_t> y_data;
2063 std::vector<uint8_t> uv_data;
2064 for (int i = 0; i < 4; i++) {
2065 auto yuv = yuvs[i];
2066 uint8_t y = std::round(yuv.x * 255.0);
2067 uint8_t u = std::round(yuv.y * 255.0);
2068 uint8_t v = std::round(yuv.z * 255.0);
2069 for (int j = 0; j < 16; j++) {
2070 y_data.push_back(y);
2071 }
2072 for (int j = 0; j < 8; j++) {
2073 uv_data.push_back(j % 2 == 0 ? u : v);
2074 }
2075 }
2076 impeller::TextureDescriptor y_texture_descriptor;
2077 y_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
2078 y_texture_descriptor.format = PixelFormat::kR8UNormInt;
2079 y_texture_descriptor.size = {8, 8};
2080 auto y_texture =
2081 context->GetResourceAllocator()->CreateTexture(y_texture_descriptor);
2082 auto y_mapping = std::make_shared<fml::DataMapping>(y_data);
2083 if (!y_texture->SetContents(y_mapping)) {
2084 FML_DLOG(ERROR) << "Could not copy contents into Y texture.";
2085 }
2086
2087 impeller::TextureDescriptor uv_texture_descriptor;
2088 uv_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
2089 uv_texture_descriptor.format = PixelFormat::kR8G8UNormInt;
2090 uv_texture_descriptor.size = {4, 4};
2091 auto uv_texture =
2092 context->GetResourceAllocator()->CreateTexture(uv_texture_descriptor);
2093 auto uv_mapping = std::make_shared<fml::DataMapping>(uv_data);
2094 if (!uv_texture->SetContents(uv_mapping)) {
2095 FML_DLOG(ERROR) << "Could not copy contents into UV texture.";
2096 }
2097
2098 return {y_texture, uv_texture};
2099 }

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

impeller::testing::DART_TEST_CASE | ( | canCreateDeviceBuffer |  | ) |

## ◆ DART_TEST_CASE() [2/12]

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

## ◆ DART_TEST_CASE() [3/12]

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

## ◆ DART_TEST_CASE() [4/12]

impeller::testing::DART_TEST_CASE | ( | canCreateTexture |  | ) |

## ◆ DART_TEST_CASE() [5/12]

impeller::testing::DART_TEST_CASE | ( | canEmplaceHostBuffer |  | ) |

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

## ◆ DART_TEST_CASE() [6/12]

impeller::testing::DART_TEST_CASE | ( | canOverwriteDeviceBuffer |  | ) |

## ◆ DART_TEST_CASE() [7/12]

impeller::testing::DART_TEST_CASE | ( | canOverwriteTexture |  | ) |

## ◆ DART_TEST_CASE() [8/12]

impeller::testing::DART_TEST_CASE | ( | deviceBufferOverwriteFailsWhenOutOfBounds |  | ) |

## ◆ DART_TEST_CASE() [9/12]

impeller::testing::DART_TEST_CASE | ( | deviceBufferOverwriteThrowsForNegativeDestinationOffset |  | ) |

## ◆ DART_TEST_CASE() [10/12]

impeller::testing::DART_TEST_CASE | ( | textureAsImageReturnsAValidUIImageHandle |  | ) |

## ◆ DART_TEST_CASE() [11/12]

impeller::testing::DART_TEST_CASE | ( | textureAsImageThrowsWhenNotShaderReadable |  | ) |

## ◆ DART_TEST_CASE() [12/12]

impeller::testing::DART_TEST_CASE | ( | textureOverwriteThrowsForWrongBufferSize |  | ) |

## ◆ GetBlendModeSelection()

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

Definition at line 1007 of file aiks_unittests.cc.

1007 {
1008 std::vector<const char*> blend_mode_names;
1009 std::vector<BlendMode> blend_mode_values;
1010 {
1011 const std::vector<std::tuple<const char*, BlendMode>> blends = {
1012 IMPELLER_FOR_EACH_BLEND_MODE(BLEND_MODE_TUPLE)};
1013 assert(blends.size() ==
1014 static_cast<size_t>(Entity::kLastAdvancedBlendMode) + 1);
1015 for (const auto& [name, mode] : blends) {
1016 blend_mode_names.push_back(name);
1017 blend_mode_values.push_back(mode);
1018 }
1019 }
1020
1021 return {blend_mode_names, blend_mode_values};
1022 }

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 1748 of file dl_unittests.cc.

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

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

## ◆ INSTANTIATE_COMPUTE_SUITE()

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [1/8]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [2/8]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [3/8]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | DirectionalGaussianBlurFilterContentsTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [4/8]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [5/8]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | EntityPassTargetTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [6/8]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [7/8]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [8/8]

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

## ◆ InstantiateTestShaderLibrary()

static void impeller::testing::InstantiateTestShaderLibrary | ( |  | ) |
| static

Definition at line 32 of file renderer_dart_unittests.cc.

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

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

## ◆ 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 684 of file aiks_unittests.cc.

688 {}) {
689 // Draw the baseline.
690 canvas.DrawRect(
691 Rect::MakeXYWH(options.position.x - 50, options.position.y, 900, 10),
692 Paint{.color = Color::Aqua().WithAlpha(0.25)});
693
694 // Mark the point at which the text is drawn.
695 canvas.DrawCircle(options.position, 5.0,
696 Paint{.color = Color::Red().WithAlpha(0.25)});
697
698 // Construct the text blob.
699 auto c_font_fixture = std::string(font_fixture);
700 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
701 if (!mapping) {
702 return false;
703 }
704 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
705 SkFont sk_font(font_mgr->makeFromData(mapping), options.font_size);
706 auto blob = SkTextBlob::MakeFromString(text.c_str(), sk_font);
707 if (!blob) {
708 return false;
709 }
710
711 // Create the Impeller text frame and draw it at the designated baseline.
712 auto frame = MakeTextFrameFromTextBlobSkia(blob);
713
714 Paint text_paint;
715 text_paint.color = options.color;
716 text_paint.mask_blur_descriptor = options.mask_blur_descriptor;
717 canvas.DrawTextFrame(frame, options.position, text_paint);
718 return true;
719 }

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 721 of file aiks_unittests.cc.

725 {}) {
726 // Draw the baseline.
727 canvas.DrawRect(
728 Rect::MakeXYWH(options.position.x - 50, options.position.y, 900, 10),
729 Paint{.color = Color::Aqua().WithAlpha(0.25)});
730
731 // Mark the point at which the text is drawn.
732 canvas.DrawCircle(options.position, 5.0,
733 Paint{.color = Color::Red().WithAlpha(0.25)});
734
735 // Construct the text blob.
736 auto mapping = flutter::testing::OpenFixtureAsMapping(font_fixture.c_str());
737 if (!mapping) {
738 return false;
739 }
740 auto typeface_stb = std::make_shared<TypefaceSTB>(std::move(mapping));
741
742 auto frame = MakeTextFrameSTB(
743 typeface_stb, Font::Metrics{.point_size = options.font_size}, text);
744
745 Paint text_paint;
746 text_paint.color = options.color;
747 canvas.DrawTextFrame(frame, options.position, text_paint);
748 return true;
749 }

Referenced by TEST_P().

## ◆ RGBToYUV()

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

Definition at line 2033 of file entity_unittests.cc.

2033 {
2034 Vector3 yuv;
2035 switch (yuv_color_space) {
2036 case YUVColorSpace::kBT601FullRange:
2037 yuv.x = rgb.x * 0.299 + rgb.y * 0.587 + rgb.z * 0.114;
2038 yuv.y = rgb.x * -0.169 + rgb.y * -0.331 + rgb.z * 0.5 + 0.5;
2039 yuv.z = rgb.x * 0.5 + rgb.y * -0.419 + rgb.z * -0.081 + 0.5;
2040 break;
2041 case YUVColorSpace::kBT601LimitedRange:
2042 yuv.x = rgb.x * 0.257 + rgb.y * 0.516 + rgb.z * 0.100 + 0.063;
2043 yuv.y = rgb.x * -0.145 + rgb.y * -0.291 + rgb.z * 0.439 + 0.5;
2044 yuv.z = rgb.x * 0.429 + rgb.y * -0.368 + rgb.z * -0.071 + 0.5;
2045 break;
2046 }
2047 return yuv;
2048 }

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

Referenced by CreateTestYUVTextures().

## ◆ TEST() [1/299]

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

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

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

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(std::move(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/299]

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(std::move(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/299]

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(std::move(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/299]

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(std::move(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/299]

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(std::move(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/299]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 = context->GetResourceAllocator()
58 ->CreateBuffer({
59 .size = 1,
60 })
61 ->AsBufferView();
62 bool result = cmd.Encode(*encoder.get());
63 EXPECT_TRUE(result);
64 EXPECT_TRUE(encoder->IsTracking(cmd.source.buffer));
65 EXPECT_TRUE(encoder->IsTracking(cmd.destination));
66 }

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

## ◆ TEST() [31/299]

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

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

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

Definition at line 68 of file blit_command_vk_unittests.cc.

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

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

## ◆ TEST() [34/299]

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

Definition at line 192 of file canvas_recorder_unittests.cc.

192 {
193 CanvasRecorder<Serializer> recorder;
194 recorder.ClipPath({});
195 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kClipPath);
196 }

References impeller::kClipPath.

## ◆ TEST() [35/299]

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

Definition at line 198 of file canvas_recorder_unittests.cc.

198 {
199 CanvasRecorder<Serializer> recorder;
200 recorder.ClipRect({});
201 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kClipRect);
202 }

References impeller::kClipRect.

## ◆ TEST() [36/299]

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

Definition at line 204 of file canvas_recorder_unittests.cc.

204 {
205 CanvasRecorder<Serializer> recorder;
206 recorder.ClipRRect({}, {});
207 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kClipRRect);
208 }

References impeller::kClipRRect.

## ◆ TEST() [37/299]

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

Definition at line 101 of file canvas_recorder_unittests.cc.

101 {
102 CanvasRecorder<Serializer> recorder;
103 recorder.Concat(Matrix());
104 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kConcat);
105 }

References impeller::kConcat.

## ◆ TEST() [38/299]

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

Definition at line 231 of file canvas_recorder_unittests.cc.

231 {
232 CanvasRecorder<Serializer> recorder;
233 recorder.DrawAtlas({}, {}, {}, {}, {}, {}, {}, {});
234 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawAtlas);
235 }

References impeller::kDrawAtlas.

## ◆ TEST() [39/299]

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

Definition at line 167 of file canvas_recorder_unittests.cc.

167 {
168 CanvasRecorder<Serializer> recorder;
169 recorder.DrawCircle(Point(), 0, Paint());
170 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawCircle);
171 }

References impeller::kDrawCircle.

## ◆ TEST() [40/299]

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

Definition at line 179 of file canvas_recorder_unittests.cc.

179 {
180 CanvasRecorder<Serializer> recorder;
181 recorder.DrawImage({}, {}, {}, {});
182 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawImage);
183 }

References impeller::kDrawImage.

## ◆ TEST() [41/299]

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

Definition at line 185 of file canvas_recorder_unittests.cc.

185 {
186 CanvasRecorder<Serializer> recorder;
187 recorder.DrawImageRect({}, {}, {}, {}, {});
188 ASSERT_EQ(recorder.GetSerializer().last_op_,
189 CanvasRecorderOp::kDrawImageRect);
190 }

References impeller::kDrawImageRect.

## ◆ TEST() [42/299]

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

Definition at line 149 of file canvas_recorder_unittests.cc.

149 {
150 CanvasRecorder<Serializer> recorder;
151 recorder.DrawPaint(Paint());
152 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawPaint);
153 }

References impeller::kDrawPaint.

## ◆ TEST() [43/299]

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

Definition at line 143 of file canvas_recorder_unittests.cc.

143 {
144 CanvasRecorder<Serializer> recorder;
145 recorder.DrawPath(Path(), Paint());
146 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawPath);
147 }

References impeller::kDrawPath.

## ◆ TEST() [44/299]

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

Definition at line 210 of file canvas_recorder_unittests.cc.

210 {
211 CanvasRecorder<Serializer> recorder;
212 recorder.DrawPicture({});
213 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawPicture);
214 }

References impeller::kDrawPicture.

## ◆ TEST() [45/299]

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

Definition at line 173 of file canvas_recorder_unittests.cc.

173 {
174 CanvasRecorder<Serializer> recorder;
175 recorder.DrawPoints(std::vector<Point>{}, 0, Paint(), PointStyle::kRound);
176 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawPoints);
177 }

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

## ◆ TEST() [46/299]

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

Definition at line 155 of file canvas_recorder_unittests.cc.

155 {
156 CanvasRecorder<Serializer> recorder;
157 recorder.DrawRect(Rect(), Paint());
158 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawRect);
159 }

References impeller::kDrawRect.

## ◆ TEST() [47/299]

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

Definition at line 161 of file canvas_recorder_unittests.cc.

161 {
162 CanvasRecorder<Serializer> recorder;
163 recorder.DrawRRect(Rect(), {}, Paint());
164 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawRRect);
165 }

References impeller::kDrawRRect.

## ◆ TEST() [48/299]

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

Definition at line 216 of file canvas_recorder_unittests.cc.

216 {
217 CanvasRecorder<Serializer> recorder;
218 recorder.DrawTextFrame({}, {}, {});
219 ASSERT_EQ(recorder.GetSerializer().last_op_,
220 CanvasRecorderOp::kDrawTextFrame);
221 }

References impeller::kDrawTextFrame.

## ◆ TEST() [49/299]

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

Definition at line 223 of file canvas_recorder_unittests.cc.

223 {
224 CanvasRecorder<Serializer> recorder;
225 auto geometry = std::shared_ptr<VerticesGeometry>(
226 new VerticesGeometry({}, {}, {}, {}, {}, {}));
227 recorder.DrawVertices(geometry, {}, {});
228 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kDrawVertices);
229 }

References impeller::kDrawVertices.

## ◆ TEST() [50/299]

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

Definition at line 107 of file canvas_recorder_unittests.cc.

107 {
108 CanvasRecorder<Serializer> recorder;
109 recorder.PreConcat(Matrix());
110 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kPreConcat);
111 }

References impeller::kPreConcat.

## ◆ TEST() [51/299]

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

Definition at line 88 of file canvas_recorder_unittests.cc.

88 {
89 CanvasRecorder<Serializer> recorder;
90 recorder.ResetTransform();
91 ASSERT_EQ(recorder.GetSerializer().last_op_,
92 CanvasRecorderOp::kResetTransform);
93 }

References impeller::kResetTransform.

## ◆ TEST() [52/299]

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

Definition at line 74 of file canvas_recorder_unittests.cc.

74 {
75 CanvasRecorder<Serializer> recorder;
76 recorder.Restore();
77 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kRestore);
78 }

References impeller::kRestore.

## ◆ TEST() [53/299]

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

Definition at line 80 of file canvas_recorder_unittests.cc.

80 {
81 CanvasRecorder<Serializer> recorder;
82 recorder.Save();
83 recorder.RestoreToCount(0);
84 ASSERT_EQ(recorder.GetSerializer().last_op_,
85 CanvasRecorderOp::kRestoreToCount);
86 }

References impeller::kRestoreToCount.

## ◆ TEST() [54/299]

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

Definition at line 137 of file canvas_recorder_unittests.cc.

137 {
138 CanvasRecorder<Serializer> recorder;
139 recorder.Rotate(Radians(0));
140 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kRotate);
141 }

References impeller::kRotate.

## ◆ TEST() [55/299]

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

Definition at line 61 of file canvas_recorder_unittests.cc.

61 {
62 CanvasRecorder<Serializer> recorder;
63 recorder.Save();
64 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kSave);
65 }

References impeller::kSave.

## ◆ TEST() [56/299]

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

Definition at line 67 of file canvas_recorder_unittests.cc.

67 {
68 CanvasRecorder<Serializer> recorder;
69 Paint paint;
70 recorder.SaveLayer(paint);
71 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kSaveLayer);
72 }

References impeller::kSaveLayer.

## ◆ TEST() [57/299]

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

Definition at line 119 of file canvas_recorder_unittests.cc.

119 {
120 CanvasRecorder<Serializer> recorder;
121 recorder.Scale(Vector2());
122 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kScale2);
123 }

References impeller::kScale2.

## ◆ TEST() [58/299]

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

Definition at line 125 of file canvas_recorder_unittests.cc.

125 {
126 CanvasRecorder<Serializer> recorder;
127 recorder.Scale(Vector3());
128 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kScale3);
129 }

References impeller::kScale3.

## ◆ TEST() [59/299]

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

Definition at line 131 of file canvas_recorder_unittests.cc.

131 {
132 CanvasRecorder<Serializer> recorder;
133 recorder.Skew(0, 0);
134 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kSkew);
135 }

References impeller::kSkew.

## ◆ TEST() [60/299]

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

Definition at line 95 of file canvas_recorder_unittests.cc.

95 {
96 CanvasRecorder<Serializer> recorder;
97 recorder.Transform(Matrix());
98 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kTransform);
99 }

References impeller::kTransform.

## ◆ TEST() [61/299]

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

Definition at line 113 of file canvas_recorder_unittests.cc.

113 {
114 CanvasRecorder<Serializer> recorder;
115 recorder.Translate(Vector3());
116 ASSERT_EQ(recorder.GetSerializer().last_op_, CanvasRecorderOp::kTranslate);
117 }

References impeller::kTranslate.

## ◆ TEST() [62/299]

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

Definition at line 32 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [63/299]

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

Definition at line 50 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [64/299]

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

Definition at line 41 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [65/299]

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

Definition at line 41 of file command_encoder_vk_unittests.cc.

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

References impeller::CommandEncoderFactoryVK::Create().

## ◆ TEST() [66/299]

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

Definition at line 15 of file command_encoder_vk_unittests.cc.

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

References impeller::CommandEncoderFactoryVK::Create().

## ◆ TEST() [67/299]

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

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

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

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

Definition at line 191 of file base_unittests.cc.

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

References impeller::ConditionVariable::Wait().

## ◆ TEST() [71/299]

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

Definition at line 146 of file base_unittests.cc.

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

References impeller::ConditionVariable::WaitFor().

## ◆ TEST() [72/299]

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

Definition at line 108 of file base_unittests.cc.

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

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

## ◆ TEST() [73/299]

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

Definition at line 129 of file base_unittests.cc.

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

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

## ◆ TEST() [74/299]

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

Definition at line 85 of file base_unittests.cc.

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

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

## ◆ TEST() [75/299]

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

Definition at line 117 of file context_vk_unittests.cc.

117 {
118 // The mocked methods don't report the presence of a validation layer but we
119 // explicitly ask for validation. Context creation should continue anyway.
120 auto context = MockVulkanContextBuilder()
121 .SetSettingsCallback([](auto& settings) {
122 settings.enable_validation = true;
123 })
124 .Build();
125 ASSERT_NE(context, nullptr);
126 const CapabilitiesVK* capabilites_vk =
127 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
128 ASSERT_FALSE(capabilites_vk->AreValidationsEnabled());
129 }

References impeller::CapabilitiesVK::AreValidationsEnabled().

## ◆ TEST() [76/299]

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

Definition at line 131 of file context_vk_unittests.cc.

131 {
132 auto context =
133 MockVulkanContextBuilder()
134 .SetSettingsCallback(
135 [](auto& settings) { settings.enable_validation = true; })
136 .SetInstanceExtensions(
137 {"VK_KHR_surface", "VK_MVK_macos_surface", "VK_EXT_debug_utils"})
138 .SetInstanceLayers({"VK_LAYER_KHRONOS_validation"})
139 .Build();
140 ASSERT_NE(context, nullptr);
141 const CapabilitiesVK* capabilites_vk =
142 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
143 ASSERT_TRUE(capabilites_vk->AreValidationsEnabled());
144 }

References impeller::CapabilitiesVK::AreValidationsEnabled().

## ◆ TEST() [77/299]

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

Definition at line 60 of file context_vk_unittests.cc.

60 {
61 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline;
62 std::shared_ptr<std::vector<std::string>> functions;
63 {
64 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
65 PipelineDescriptor pipeline_desc;
66 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
67 PipelineFuture<PipelineDescriptor> pipeline_future =
68 context->GetPipelineLibrary()->GetPipeline(pipeline_desc);
69 pipeline = pipeline_future.Get();
70 ASSERT_TRUE(pipeline);
71 functions = GetMockVulkanFunctions(context->GetDevice());
72 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
73 "vkCreateGraphicsPipelines") != functions->end());
74 }
75 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
76 "vkDestroyDevice") != functions->end());
77 }

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

## ◆ TEST() [78/299]

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

Definition at line 101 of file context_vk_unittests.cc.

101 {
102 std::shared_ptr<PipelineLibrary> pipeline_library;
103 std::shared_ptr<std::vector<std::string>> functions;
104 {
105 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
106 PipelineDescriptor pipeline_desc;
107 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
108 pipeline_library = context->GetPipelineLibrary();
109 functions = GetMockVulkanFunctions(context->GetDevice());
110 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
111 "vkCreatePipelineCache") != functions->end());
112 }
113 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
114 "vkDestroyDevice") != functions->end());
115 }

References impeller::PipelineDescriptor::SetVertexDescriptor().

## ◆ TEST() [79/299]

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

Definition at line 14 of file context_vk_unittests.cc.

14 {
15 std::weak_ptr<ContextVK> weak_context;
16 std::weak_ptr<CommandPoolVK> weak_pool;
17 {
18 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
19 auto const pool = context->GetCommandPoolRecycler()->Get();
20 weak_pool = pool;
21 weak_context = context;
22 ASSERT_TRUE(weak_pool.lock());
23 ASSERT_TRUE(weak_context.lock());
24 }
25 ASSERT_FALSE(weak_pool.lock());
26 ASSERT_FALSE(weak_context.lock());
27 }

## ◆ TEST() [80/299]

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

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_main;
32
33 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
34 weak_pool_main = context->GetCommandPoolRecycler()->Get();
35 weak_context = context;
36 ASSERT_TRUE(weak_pool_main.lock());
37 ASSERT_TRUE(weak_context.lock());
38
39 // Start a second thread that obtains a command pool.
40 fml::AutoResetWaitableEvent latch1, latch2;
41 std::weak_ptr<CommandPoolVK> weak_pool_thread;
42 std::thread thread([&]() {
43 weak_pool_thread = context->GetCommandPoolRecycler()->Get();
44 latch1.Signal();
45 latch2.Wait();
46 });
47
48 // Delete the ContextVK on the main thread.
49 latch1.Wait();
50 context.reset();
51 ASSERT_FALSE(weak_pool_main.lock());
52 ASSERT_FALSE(weak_context.lock());
53
54 // Stop the second thread and check that its command pool has been deleted.
55 latch2.Signal();
56 thread.join();
57 ASSERT_FALSE(weak_pool_thread.lock());
58 }

## ◆ TEST() [81/299]

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

Definition at line 79 of file context_vk_unittests.cc.

79 {
80 std::shared_ptr<const ShaderFunction> shader_function;
81 std::shared_ptr<std::vector<std::string>> functions;
82 {
83 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
84 PipelineDescriptor pipeline_desc;
85 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
86 std::vector<uint8_t> data = {0x03, 0x02, 0x23, 0x07};
87 context->GetShaderLibrary()->RegisterFunction(
88 "foobar", ShaderStage::kFragment,
89 std::make_shared<fml::DataMapping>(data), [](bool) {});
90 shader_function = context->GetShaderLibrary()->GetFunction(
91 "foobar_fragment_main", ShaderStage::kFragment);
92 ASSERT_TRUE(shader_function);
93 functions = GetMockVulkanFunctions(context->GetDevice());
94 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
95 "vkCreateShaderModule") != functions->end());
96 }
97 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
98 "vkDestroyDevice") != functions->end());
99 }

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

## ◆ TEST() [82/299]

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

Definition at line 26 of file descriptor_pool_vk_unittests.cc.

26 {
27 auto const context = MockVulkanContextBuilder().Build();
28 auto const [pool1, capacity] = context->GetDescriptorPoolRecycler()->Get(1);
29
30 // Rounds up to a minimum of 64.
31 EXPECT_EQ(capacity, 64u);
32
33 auto const [pool2, capacity_2] =
34 context->GetDescriptorPoolRecycler()->Get(1023);
35
36 // Rounds up to the next power of two.
37 EXPECT_EQ(capacity_2, 1024u);
38
39 context->Shutdown();
40 }

## ◆ TEST() [83/299]

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(1024);
18 auto const [pool2, __] = context->GetDescriptorPoolRecycler()->Get(1024);
19
20 // The two descriptor pools should be different.
21 EXPECT_NE(pool1.get(), pool2.get());
22
23 context->Shutdown();
24 }

## ◆ TEST() [84/299]

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

Definition at line 101 of file descriptor_pool_vk_unittests.cc.

101 {
102 auto const context = MockVulkanContextBuilder().Build();
103
104 // Create 33 pools
105 {
106 std::vector<std::unique_ptr<DescriptorPoolVK>> pools;
107 for (auto i = 0u; i < 33; i++) {
108 auto pool = std::make_unique<DescriptorPoolVK>(context);
109 pool->AllocateDescriptorSets(1024, 1024, 1024, {});
110 pools.push_back(std::move(pool));
111 }
112 }
113
114 // See note above.
115 for (auto i = 0u; i < 2; i++) {
116 auto waiter = fml::AutoResetWaitableEvent();
117 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
118 {
119 UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
120 std::move(rattle));
121 }
122 waiter.Wait();
123 }
124
125 auto const called = GetMockVulkanFunctions(context->GetDevice());
126 EXPECT_EQ(
127 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
128 33u);
129 EXPECT_EQ(std::count(called->begin(), called->end(), "vkResetDescriptorPool"),
130 33u);
131
132 // Now create 33 more descriptor pools and observe that only one more is
133 // allocated.
134 {
135 std::vector<std::unique_ptr<DescriptorPoolVK>> pools;
136 for (auto i = 0u; i < 33; i++) {
137 auto pool = std::make_unique<DescriptorPoolVK>(context);
138 pool->AllocateDescriptorSets(1024, 1024, 1024, {});
139 pools.push_back(std::move(pool));
140 }
141 }
142
143 for (auto i = 0u; i < 2; i++) {
144 auto waiter = fml::AutoResetWaitableEvent();
145 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
146 {
147 UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
148 std::move(rattle));
149 }
150 waiter.Wait();
151 }
152
153 auto const called_twice = GetMockVulkanFunctions(context->GetDevice());
154 // 32 of the descriptor pools were recycled, so only one more is created.
155 EXPECT_EQ(
156 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
157 34u);
158
159 context->Shutdown();
160 }

## ◆ TEST() [85/299]

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

Definition at line 63 of file descriptor_pool_vk_unittests.cc.

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

## ◆ TEST() [86/299]

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

Definition at line 67 of file directional_gaussian_blur_filter_contents_unittests.cc.

67 {
68 Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
69 auto contents = std::make_unique<DirectionalGaussianBlurFilterContents>();
70 contents->SetSigma(Sigma{sigma_radius_1});
71 contents->SetDirection({1.0, 0.0});
72 std::optional<Rect> coverage = contents->GetFilterSourceCoverage(
73 /*effect_transform=*/Matrix::MakeScale({2.0, 2.0, 1.0}),
74 /*output_limit=*/Rect::MakeLTRB(100, 100, 200, 200));
75 ASSERT_EQ(coverage, Rect::MakeLTRB(100 - 2, 100, 200 + 2, 200));
76 }

References impeller::TRect< Scalar >::MakeLTRB(), and impeller::Matrix::MakeScale().

## ◆ TEST() [87/299]

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

Definition at line 1785 of file dl_unittests.cc.

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

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

## ◆ TEST() [88/299]

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

Definition at line 1762 of file dl_unittests.cc.

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

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

## ◆ TEST() [89/299]

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

Definition at line 20 of file geometry_unittests.cc.

20 {
21 auto path = PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath();
22 auto geometry = Geometry::MakeFillPath(
23 std::move(path), /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
24 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
25 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
26 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
27 ASSERT_TRUE(geometry->CoversArea({}, Rect()));
28 }

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

## ◆ TEST() [90/299]

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

Definition at line 30 of file geometry_unittests.cc.

30 {
31 auto path = PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath();
32 auto geometry = Geometry::MakeFillPath(std::move(path));
33 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
34 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
35 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
36 ASSERT_FALSE(geometry->CoversArea({}, Rect()));
37 }

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

## ◆ TEST() [91/299]

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

Definition at line 39 of file geometry_unittests.cc.

39 {
40 {
41 auto geometry = Geometry::MakeLine({10, 10}, {20, 10}, 2, Cap::kButt);
42 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(10, 9, 20, 11));
43 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(10, 9, 20, 11)));
44 }
45
46 {
47 auto geometry = Geometry::MakeLine({10, 10}, {20, 10}, 2, Cap::kSquare);
48 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 9, 21, 11));
49 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 9, 21, 11)));
50 }
51
52 {
53 auto geometry = Geometry::MakeLine({10, 10}, {10, 20}, 2, Cap::kButt);
54 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 10, 11, 20));
55 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 10, 11, 20)));
56 }
57
58 {
59 auto geometry = Geometry::MakeLine({10, 10}, {10, 20}, 2, Cap::kSquare);
60 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 9, 11, 21));
61 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 9, 11, 21)));
62 }
63 }

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

## ◆ TEST() [92/299]

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

Definition at line 12 of file geometry_unittests.cc.

12 {
13 auto geometry = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 100, 100));
14 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
15 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
16 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
17 ASSERT_TRUE(geometry->CoversArea({}, Rect()));
18 }

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

## ◆ TEST() [93/299]

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

Definition at line 65 of file geometry_unittests.cc.

65 {
66 auto geometry =
67 Geometry::MakeRoundRect(Rect::MakeLTRB(0, 0, 100, 100), Size(20, 20));
68 EXPECT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(15, 15, 85, 85)));
69 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(20, 20, 80, 80)));
70 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(30, 1, 70, 99)));
71 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 30, 99, 70)));
72 }

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

## ◆ TEST() [94/299]

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

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

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

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

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

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

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

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

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

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

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

Definition at line 375 of file gaussian_blur_filter_contents_unittests.cc.

375 {
376 Scalar sigma = 1.0;
377 Scalar radius = GaussianBlurFilterContents::CalculateBlurRadius(
378 GaussianBlurFilterContents::ScaleSigma(sigma));
379 Scalar derived_sigma = CalculateSigmaForBlurRadius(radius);
380
381 EXPECT_NEAR(sigma, derived_sigma, 0.01f);
382 }

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

## ◆ TEST() [105/299]

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

Definition at line 167 of file gaussian_blur_filter_contents_unittests.cc.

167 {
168 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1.0f), 1);
169 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(2.0f), 1);
170 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(3.0f), 1);
171 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(4.0f), 1);
172 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(16.0f), 0.25);
173 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1024.0f), 4.f / 1024.f);
174 }

References impeller::GaussianBlurFilterContents::CalculateScale().

## ◆ TEST() [106/299]

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

Definition at line 384 of file gaussian_blur_filter_contents_unittests.cc.

384 {
385 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
386 .blur_sigma = 1,
387 .blur_radius = 5,
388 .step_size = 1};
389 KernelPipeline::FragmentShader::KernelSamples samples =
390 GenerateBlurInfo(parameters);
391 EXPECT_EQ(samples.sample_count, 11);
392
393 // Coefficients should add up to 1.
394 Scalar tally = 0;
395 for (int i = 0; i < samples.sample_count; ++i) {
396 tally += samples.samples[i].coefficient;
397 }
398 EXPECT_FLOAT_EQ(tally, 1.0f);
399
400 // Verify the shape of the curve.
401 for (int i = 0; i < 5; ++i) {
402 EXPECT_FLOAT_EQ(samples.samples[i].coefficient,
403 samples.samples[10 - i].coefficient);
404 EXPECT_TRUE(samples.samples[i + 1].coefficient >
405 samples.samples[i].coefficient);
406 }
407 }

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

## ◆ TEST() [107/299]

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

Definition at line 71 of file gaussian_blur_filter_contents_unittests.cc.

71 {
72 GaussianBlurFilterContents contents(/*sigma_x=*/0.0, /*sigma_y=*/0.0,
73 Entity::TileMode::kDecal);
74 FilterInput::Vector inputs = {};
75 Entity entity;
76 std::optional<Rect> coverage =
77 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
78 ASSERT_FALSE(coverage.has_value());
79 }

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

## ◆ TEST() [108/299]

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

Definition at line 81 of file gaussian_blur_filter_contents_unittests.cc.

81 {
82 GaussianBlurFilterContents contents(/*sigma_x=*/0.0, /*sigma_y=*/0.0,
83 Entity::TileMode::kDecal);
84 FilterInput::Vector inputs = {
85 FilterInput::Make(Rect::MakeLTRB(10, 10, 110, 110))};
86 Entity entity;
87 std::optional<Rect> coverage =
88 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
89 ASSERT_EQ(coverage, Rect::MakeLTRB(10, 10, 110, 110));
90 }

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

## ◆ TEST() [109/299]

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

Definition at line 92 of file gaussian_blur_filter_contents_unittests.cc.

92 {
93 Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
94 GaussianBlurFilterContents contents(/*sigma_x=*/sigma_radius_1,
95 /*sigma_y=*/sigma_radius_1,
96 Entity::TileMode::kDecal);
97 FilterInput::Vector inputs = {
98 FilterInput::Make(Rect::MakeLTRB(100, 100, 200, 200))};
99 Entity entity;
100 std::optional<Rect> coverage =
101 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
102 EXPECT_TRUE(coverage.has_value());
103 if (coverage.has_value()) {
104 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(99, 99, 201, 201));
105 }
106 }

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

## ◆ TEST() [110/299]

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

Definition at line 64 of file gaussian_blur_filter_contents_unittests.cc.

64 {
65 GaussianBlurFilterContents contents(/*sigma_x=*/0.0, /*sigma_y=*/0.0,
66 Entity::TileMode::kDecal);
67 EXPECT_EQ(contents.GetSigmaX(), 0.0);
68 EXPECT_EQ(contents.GetSigmaY(), 0.0);
69 }

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

## ◆ TEST() [111/299]

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

Definition at line 157 of file gaussian_blur_filter_contents_unittests.cc.

157 {
158 Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
159 auto contents = std::make_unique<GaussianBlurFilterContents>(
160 sigma_radius_1, sigma_radius_1, Entity::TileMode::kDecal);
161 std::optional<Rect> coverage = contents->GetFilterSourceCoverage(
162 /*effect_transform=*/Matrix::MakeScale({2.0, 2.0, 1.0}),
163 /*output_limit=*/Rect::MakeLTRB(100, 100, 200, 200));
164 ASSERT_EQ(coverage, Rect::MakeLTRB(100 - 2, 100 - 2, 200 + 2, 200 + 2));
165 }

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

## ◆ TEST() [112/299]

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

Definition at line 1452 of file geometry_unittests.cc.

1452 {
1453 using BlendT = std::underlying_type_t<BlendMode>;
1454 for (BlendT i = 0; i <= static_cast<BlendT>(BlendMode::kLast); i++) {
1455 auto mode = static_cast<BlendMode>(i);
1456 auto result = BlendModeToString(mode);
1457 switch (mode) { IMPELLER_FOR_EACH_BLEND_MODE(_BLEND_MODE_NAME_CHECK) }
1458 }
1459 }

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

## ◆ TEST() [113/299]

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

Definition at line 1461 of file geometry_unittests.cc.

1461 {
1462 {
1463 auto deg = Degrees{90.0};
1464 Radians rad = deg;
1465 ASSERT_FLOAT_EQ(rad.radians, kPiOver2);
1466 }
1467 }

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

## ◆ TEST() [114/299]

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

Definition at line 604 of file geometry_unittests.cc.

604 {
605 {
606 Point p1(1.0, 2.0);
607 IPoint p2 = static_cast<IPoint>(p1);
608 ASSERT_EQ(p2.x, 1u);
609 ASSERT_EQ(p2.y, 2u);
610 }
611
612 {
613 Size s1(1.0, 2.0);
614 ISize s2 = static_cast<ISize>(s1);
615 ASSERT_EQ(s2.width, 1u);
616 ASSERT_EQ(s2.height, 2u);
617 }
618
619 {
620 Size s1(1.0, 2.0);
621 Point p1 = static_cast<Point>(s1);
622 ASSERT_EQ(p1.x, 1u);
623 ASSERT_EQ(p1.y, 2u);
624 }
625
626 {
627 Rect r1 = Rect::MakeXYWH(1.0, 2.0, 3.0, 4.0);
628 IRect r2 = static_cast<IRect>(r1);
629 ASSERT_EQ(r2.GetOrigin().x, 1u);
630 ASSERT_EQ(r2.GetOrigin().y, 2u);
631 ASSERT_EQ(r2.GetSize().width, 3u);
632 ASSERT_EQ(r2.GetSize().height, 4u);
633 ASSERT_EQ(r2.GetX(), 1u);
634 ASSERT_EQ(r2.GetY(), 2u);
635 ASSERT_EQ(r2.GetWidth(), 3u);
636 ASSERT_EQ(r2.GetHeight(), 4u);
637 }
638 }

References impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetOrigin(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TSize< T >::height, impeller::TRect< Scalar >::MakeXYWH(), impeller::TSize< T >::width, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST() [115/299]

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

Definition at line 591 of file geometry_unittests.cc.

591 {
592 ASSERT_EQ((Size{128, 128}.MipCount()), 7u);
593 ASSERT_EQ((Size{128, 256}.MipCount()), 8u);
594 ASSERT_EQ((Size{128, 130}.MipCount()), 8u);
595 ASSERT_EQ((Size{128, 257}.MipCount()), 9u);
596 ASSERT_EQ((Size{257, 128}.MipCount()), 9u);
597 ASSERT_EQ((Size{128, 0}.MipCount()), 1u);
598 ASSERT_EQ((Size{128, -25}.MipCount()), 1u);
599 ASSERT_EQ((Size{-128, 25}.MipCount()), 1u);
600 ASSERT_EQ((Size{1, 1}.MipCount()), 1u);
601 ASSERT_EQ((Size{0, 0}.MipCount()), 1u);
602 }

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

## ◆ TEST() [116/299]

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

Definition at line 640 of file geometry_unittests.cc.

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

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

## ◆ TEST() [117/299]

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

Definition at line 670 of file geometry_unittests.cc.

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

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

## ◆ TEST() [118/299]

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

Definition at line 1174 of file geometry_unittests.cc.

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

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

## ◆ TEST() [119/299]

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

Definition at line 1208 of file geometry_unittests.cc.

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

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

## ◆ TEST() [120/299]

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

Definition at line 822 of file geometry_unittests.cc.

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

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

## ◆ TEST() [121/299]

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

Definition at line 1124 of file geometry_unittests.cc.

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

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

## ◆ TEST() [122/299]

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

Definition at line 1381 of file geometry_unittests.cc.

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

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

## ◆ TEST() [123/299]

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

Definition at line 1341 of file geometry_unittests.cc.

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

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

## ◆ TEST() [124/299]

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

Definition at line 1319 of file geometry_unittests.cc.

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

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

## ◆ TEST() [125/299]

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

Definition at line 1407 of file geometry_unittests.cc.

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

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

## ◆ TEST() [126/299]

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

Definition at line 1361 of file geometry_unittests.cc.

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

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

## ◆ TEST() [127/299]

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

Definition at line 1276 of file geometry_unittests.cc.

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

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

## ◆ TEST() [128/299]

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

Definition at line 2061 of file geometry_unittests.cc.

2061 {
2062 {
2063 std::stringstream stream;
2064 Color m;
2065 stream << m;
2066 ASSERT_EQ(stream.str(), "(0, 0, 0, 0)");
2067 }
2068
2069 {
2070 std::stringstream stream;
2071 Color m(1, 2, 3, 4);
2072 stream << m;
2073 ASSERT_EQ(stream.str(), "(1, 2, 3, 4)");
2074 }
2075 }

## ◆ TEST() [129/299]

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

Definition at line 1299 of file geometry_unittests.cc.

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

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

## ◆ TEST() [130/299]

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

Definition at line 1427 of file geometry_unittests.cc.

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

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

## ◆ TEST() [131/299]

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

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

Definition at line 2083 of file geometry_unittests.cc.

2083 {
2084 {
2085 // Simple 2 color gradient produces color buffer containing exactly those
2086 // values.
2087 std::vector<Color> colors = {Color::Red(), Color::Blue()};
2088 std::vector<Scalar> stops = {0.0, 1.0};
2089
2090 auto gradient = CreateGradientBuffer(colors, stops);
2091
2092 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, colors);
2093 ASSERT_EQ(gradient.texture_size, 2u);
2094 }
2095
2096 {
2097 // Gradient with duplicate stops does not create an empty texture.
2098 std::vector<Color> colors = {Color::Red(), Color::Yellow(), Color::Black(),
2099 Color::Blue()};
2100 std::vector<Scalar> stops = {0.0, 0.25, 0.25, 1.0};
2101
2102 auto gradient = CreateGradientBuffer(colors, stops);
2103 ASSERT_EQ(gradient.texture_size, 5u);
2104 }
2105
2106 {
2107 // Simple N color gradient produces color buffer containing exactly those
2108 // values.
2109 std::vector<Color> colors = {Color::Red(), Color::Blue(), Color::Green(),
2110 Color::White()};
2111 std::vector<Scalar> stops = {0.0, 0.33, 0.66, 1.0};
2112
2113 auto gradient = CreateGradientBuffer(colors, stops);
2114
2115 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, colors);
2116 ASSERT_EQ(gradient.texture_size, 4u);
2117 }
2118
2119 {
2120 // Gradient with color stops will lerp and scale buffer.
2121 std::vector<Color> colors = {Color::Red(), Color::Blue(), Color::Green()};
2122 std::vector<Scalar> stops = {0.0, 0.25, 1.0};
2123
2124 auto gradient = CreateGradientBuffer(colors, stops);
2125
2126 std::vector<Color> lerped_colors = {
2127 Color::Red(),
2128 Color::Blue(),
2129 Color::Lerp(Color::Blue(), Color::Green(), 0.3333),
2130 Color::Lerp(Color::Blue(), Color::Green(), 0.6666),
2131 Color::Green(),
2132 };
2133 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, lerped_colors);
2134 ASSERT_EQ(gradient.texture_size, 5u);
2135 }
2136
2137 {
2138 // Gradient size is capped at 1024.
2139 std::vector<Color> colors = {};
2140 std::vector<Scalar> stops = {};
2141 for (auto i = 0u; i < 1025; i++) {
2142 colors.push_back(Color::Blue());
2143 stops.push_back(i / 1025.0);
2144 }
2145
2146 auto gradient = CreateGradientBuffer(colors, stops);
2147
2148 ASSERT_EQ(gradient.texture_size, 1024u);
2149 ASSERT_EQ(gradient.color_bytes.size(), 1024u * 4);
2150 }
2151 }

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

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

Definition at line 2153 of file geometry_unittests.cc.

2153 {
2154 #ifdef FML_OS_WIN
2155 GTEST_SKIP() << "Half-precision floats (IEEE 754) are not portable and "
2156 "unavailable on Windows.";
2157 #else
2158 ASSERT_EQ(ScalarToHalf(0.0), 0.0f16);
2159 ASSERT_EQ(ScalarToHalf(0.05), 0.05f16);
2160 ASSERT_EQ(ScalarToHalf(2.43), 2.43f16);
2161 ASSERT_EQ(ScalarToHalf(-1.45), -1.45f16);
2162
2163 // 65504 is the largest possible half.
2164 ASSERT_EQ(ScalarToHalf(65504.0f), 65504.0f16);
2165 ASSERT_EQ(ScalarToHalf(65504.0f + 1), 65504.0f16);
2166
2167 // Colors
2168 ASSERT_EQ(HalfVector4(Color::Red()),
2169 HalfVector4(1.0f16, 0.0f16, 0.0f16, 1.0f16));
2170 ASSERT_EQ(HalfVector4(Color::Green()),
2171 HalfVector4(0.0f16, 1.0f16, 0.0f16, 1.0f16));
2172 ASSERT_EQ(HalfVector4(Color::Blue()),
2173 HalfVector4(0.0f16, 0.0f16, 1.0f16, 1.0f16));
2174 ASSERT_EQ(HalfVector4(Color::Black().WithAlpha(0)),
2175 HalfVector4(0.0f16, 0.0f16, 0.0f16, 0.0f16));
2176
2177 ASSERT_EQ(HalfVector3(Vector3(4.0, 6.0, -1.0)),
2178 HalfVector3(4.0f16, 6.0f16, -1.0f16));
2179 ASSERT_EQ(HalfVector2(Vector2(4.0, 6.0)), HalfVector2(4.0f16, 6.0f16));
2180
2181 ASSERT_EQ(Half(0.5f), Half(0.5f16));
2182 ASSERT_EQ(Half(0.5), Half(0.5f16));
2183 ASSERT_EQ(Half(5), Half(5.0f16));
2184 #endif // FML_OS_WIN
2185 }

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

## ◆ TEST() [134/299]

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

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

## ◆ TEST() [136/299]

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

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

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

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

Definition at line 405 of file geometry_unittests.cc.

405 {
406 {
407 auto m = Matrix();
408 Vector3 x = m.GetBasisX();
409 Vector3 y = m.GetBasisY();
410 Vector3 z = m.GetBasisZ();
411 ASSERT_VECTOR3_NEAR(x, Vector3(1, 0, 0));
412 ASSERT_VECTOR3_NEAR(y, Vector3(0, 1, 0));
413 ASSERT_VECTOR3_NEAR(z, Vector3(0, 0, 1));
414 }
415
416 {
417 auto m = Matrix::MakeRotationZ(Radians{kPiOver2}) *
418 Matrix::MakeRotationX(Radians{kPiOver2}) *
419 Matrix::MakeScale(Vector3(2, 3, 4));
420 Vector3 x = m.GetBasisX();
421 Vector3 y = m.GetBasisY();
422 Vector3 z = m.GetBasisZ();
423 ASSERT_VECTOR3_NEAR(x, Vector3(0, 2, 0));
424 ASSERT_VECTOR3_NEAR(y, Vector3(0, 0, 3));
425 ASSERT_VECTOR3_NEAR(z, Vector3(4, 0, 0));
426 }
427 }

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

## ◆ TEST() [140/299]

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

Definition at line 429 of file geometry_unittests.cc.

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

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

## ◆ TEST() [141/299]

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

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 }

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

## ◆ TEST() [143/299]

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

Definition at line 452 of file geometry_unittests.cc.

452 {
453 {
454 auto m = Matrix::MakeTranslation({1, 2, 3});
455 bool result = m.IsAligned();
456 ASSERT_TRUE(result);
457 }
458
459 {
460 auto m = Matrix::MakeRotationZ(Degrees{123});
461 bool result = m.IsAligned();
462 ASSERT_FALSE(result);
463 }
464 }

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

## ◆ TEST() [144/299]

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

Definition at line 492 of file geometry_unittests.cc.

492 {
493 {
494 auto m = Matrix::MakeLookAt(Vector3(0, 0, -1), Vector3(0, 0, 1),
495 Vector3(0, 1, 0));
496 auto expected = Matrix{
497 1, 0, 0, 0, //
498 0, 1, 0, 0, //
499 0, 0, 1, 0, //
500 0, 0, 1, 1, //
501 };
502 ASSERT_MATRIX_NEAR(m, expected);
503 }
504
505 // Sideways tilt.
506 {
507 auto m = Matrix::MakeLookAt(Vector3(0, 0, -1), Vector3(0, 0, 1),
508 Vector3(1, 1, 0).Normalize());
509
510 // clang-format off
511 auto expected = Matrix{
512 k1OverSqrt2, k1OverSqrt2, 0, 0,
513 -k1OverSqrt2, k1OverSqrt2, 0, 0,
514 0, 0, 1, 0,
515 0, 0, 1, 1,
516 };
517 // clang-format on
518 ASSERT_MATRIX_NEAR(m, expected);
519 }
520
521 // Half way between +x and -y, yaw 90
522 {
523 auto m =
524 Matrix::MakeLookAt(Vector3(), Vector3(10, -10, 0), Vector3(0, 0, -1));
525
526 // clang-format off
527 auto expected = Matrix{
528 -k1OverSqrt2, 0, k1OverSqrt2, 0,
529 -k1OverSqrt2, 0, -k1OverSqrt2, 0,
530 0, -1, 0, 0,
531 0, 0, 0, 1,
532 };
533 // clang-format on
534 ASSERT_MATRIX_NEAR(m, expected);
535 }
536 }

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

## ◆ TEST() [145/299]

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

Definition at line 357 of file geometry_unittests.cc.

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

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

## ◆ TEST() [146/299]

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

Definition at line 381 of file geometry_unittests.cc.

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

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

## ◆ TEST() [147/299]

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

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

Definition at line 1986 of file geometry_unittests.cc.

1986 {
1987 {
1988 std::stringstream stream;
1989 Matrix m;
1990 stream << m;
1991 ASSERT_EQ(stream.str(), R"((
1992 1.000000, 0.000000, 0.000000, 0.000000,
1993 0.000000, 1.000000, 0.000000, 0.000000,
1994 0.000000, 0.000000, 1.000000, 0.000000,
1995 0.000000, 0.000000, 0.000000, 1.000000,
1996 ))");
1997 }
1998
1999 {
2000 std::stringstream stream;
2001 Matrix m = Matrix::MakeTranslation(Vector3(10, 20, 30));
2002 stream << m;
2003
2004 ASSERT_EQ(stream.str(), R"((
2005 1.000000, 0.000000, 0.000000, 10.000000,
2006 0.000000, 1.000000, 0.000000, 20.000000,
2007 0.000000, 0.000000, 1.000000, 30.000000,
2008 0.000000, 0.000000, 0.000000, 1.000000,
2009 ))");
2010 }
2011 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST() [149/299]

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

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

Definition at line 466 of file geometry_unittests.cc.

466 {
467 {
468 auto m = Matrix();
469 bool result = m.IsTranslationScaleOnly();
470 ASSERT_TRUE(result);
471 }
472
473 {
474 auto m = Matrix::MakeScale(Vector3(2, 3, 4));
475 bool result = m.IsTranslationScaleOnly();
476 ASSERT_TRUE(result);
477 }
478
479 {
480 auto m = Matrix::MakeTranslation(Vector3(2, 3, 4));
481 bool result = m.IsTranslationScaleOnly();
482 ASSERT_TRUE(result);
483 }
484
485 {
486 auto m = Matrix::MakeRotationZ(Degrees(10));
487 bool result = m.IsTranslationScaleOnly();
488 ASSERT_FALSE(result);
489 }
490 }

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

## ◆ TEST() [151/299]

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

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

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

Definition at line 1604 of file geometry_unittests.cc.

1604 {
1605 Rect a = Rect::MakeLTRB(0, 0, 110, 110);
1606 Rect b = Rect::MakeLTRB(100, 100, 200, 200);
1607 Rect c = Rect::MakeLTRB(100, 0, 200, 110);
1608
1609 // NullOpt, NullOpt
1610 EXPECT_FALSE(Rect::Intersection(std::nullopt, std::nullopt).has_value());
1611 EXPECT_EQ(Rect::Intersection(std::nullopt, std::nullopt), std::nullopt);
1612
1613 auto test1 = [](const Rect& r) {
1614 // Rect, NullOpt
1615 EXPECT_TRUE(Rect::Intersection(r, std::nullopt).has_value());
1616 EXPECT_EQ(Rect::Intersection(r, std::nullopt).value(), r);
1617
1618 // OptRect, NullOpt
1619 EXPECT_TRUE(Rect::Intersection(std::optional(r), std::nullopt).has_value());
1620 EXPECT_EQ(Rect::Intersection(std::optional(r), std::nullopt).value(), r);
1621
1622 // NullOpt, Rect
1623 EXPECT_TRUE(Rect::Intersection(std::nullopt, r).has_value());
1624 EXPECT_EQ(Rect::Intersection(std::nullopt, r).value(), r);
1625
1626 // NullOpt, OptRect
1627 EXPECT_TRUE(Rect::Intersection(std::nullopt, std::optional(r)).has_value());
1628 EXPECT_EQ(Rect::Intersection(std::nullopt, std::optional(r)).value(), r);
1629 };
1630
1631 test1(a);
1632 test1(b);
1633 test1(c);
1634
1635 auto test2 = [](const Rect& a, const Rect& b, const Rect& i) {
1636 ASSERT_EQ(a.Intersection(b), i);
1637
1638 // Rect, OptRect
1639 EXPECT_TRUE(Rect::Intersection(a, std::optional(b)).has_value());
1640 EXPECT_EQ(Rect::Intersection(a, std::optional(b)).value(), i);
1641
1642 // OptRect, Rect
1643 EXPECT_TRUE(Rect::Intersection(std::optional(a), b).has_value());
1644 EXPECT_EQ(Rect::Intersection(std::optional(a), b).value(), i);
1645
1646 // OptRect, OptRect
1647 EXPECT_TRUE(
1648 Rect::Intersection(std::optional(a), std::optional(b)).has_value());
1649 EXPECT_EQ(Rect::Intersection(std::optional(a), std::optional(b)).value(),
1650 i);
1651 };
1652
1653 test2(a, b, Rect::MakeLTRB(100, 100, 110, 110));
1654 test2(a, c, Rect::MakeLTRB(100, 0, 110, 110));
1655 test2(b, c, Rect::MakeLTRB(100, 100, 200, 110));
1656 }

References impeller::TRect< Scalar >::Intersection(), impeller::TRect< T >::Intersection(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [154/299]

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

Definition at line 1503 of file geometry_unittests.cc.

1503 {
1504 Rect a = Rect::MakeLTRB(0, 0, 100, 100);
1505 Rect b = Rect::MakeLTRB(100, 100, 200, 200);
1506 Rect c = Rect::MakeLTRB(100, 0, 200, 100);
1507
1508 // NullOpt, NullOpt
1509 EXPECT_FALSE(Rect::Union(std::nullopt, std::nullopt).has_value());
1510 EXPECT_EQ(Rect::Union(std::nullopt, std::nullopt), std::nullopt);
1511
1512 auto test1 = [](const Rect& r) {
1513 // Rect, NullOpt
1514 EXPECT_TRUE(Rect::Union(r, std::nullopt).has_value());
1515 EXPECT_EQ(Rect::Union(r, std::nullopt).value(), r);
1516
1517 // OptRect, NullOpt
1518 EXPECT_TRUE(Rect::Union(std::optional(r), std::nullopt).has_value());
1519 EXPECT_EQ(Rect::Union(std::optional(r), std::nullopt).value(), r);
1520
1521 // NullOpt, Rect
1522 EXPECT_TRUE(Rect::Union(std::nullopt, r).has_value());
1523 EXPECT_EQ(Rect::Union(std::nullopt, r).value(), r);
1524
1525 // NullOpt, OptRect
1526 EXPECT_TRUE(Rect::Union(std::nullopt, std::optional(r)).has_value());
1527 EXPECT_EQ(Rect::Union(std::nullopt, std::optional(r)).value(), r);
1528 };
1529
1530 test1(a);
1531 test1(b);
1532 test1(c);
1533
1534 auto test2 = [](const Rect& a, const Rect& b, const Rect& u) {
1535 ASSERT_EQ(a.Union(b), u);
1536
1537 // Rect, OptRect
1538 EXPECT_TRUE(Rect::Union(a, std::optional(b)).has_value());
1539 EXPECT_EQ(Rect::Union(a, std::optional(b)).value(), u);
1540
1541 // OptRect, Rect
1542 EXPECT_TRUE(Rect::Union(std::optional(a), b).has_value());
1543 EXPECT_EQ(Rect::Union(std::optional(a), b).value(), u);
1544
1545 // OptRect, OptRect
1546 EXPECT_TRUE(Rect::Union(std::optional(a), std::optional(b)).has_value());
1547 EXPECT_EQ(Rect::Union(std::optional(a), std::optional(b)).value(), u);
1548 };
1549
1550 test2(a, b, Rect::MakeLTRB(0, 0, 200, 200));
1551 test2(a, c, Rect::MakeLTRB(0, 0, 200, 100));
1552 test2(b, c, Rect::MakeLTRB(100, 0, 200, 200));
1553 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< T >::Union(), and impeller::TRect< Scalar >::Union().

## ◆ TEST() [155/299]

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

Definition at line 962 of file geometry_unittests.cc.

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

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

## ◆ TEST() [156/299]

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

Definition at line 969 of file geometry_unittests.cc.

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

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

## ◆ TEST() [157/299]

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

Definition at line 1061 of file geometry_unittests.cc.

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

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

## ◆ TEST() [158/299]

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

Definition at line 917 of file geometry_unittests.cc.

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

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

## ◆ TEST() [159/299]

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

Definition at line 897 of file geometry_unittests.cc.

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

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

## ◆ TEST() [160/299]

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

Definition at line 1040 of file geometry_unittests.cc.

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

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

## ◆ TEST() [161/299]

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

Definition at line 702 of file geometry_unittests.cc.

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

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

## ◆ TEST() [162/299]

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

Definition at line 1103 of file geometry_unittests.cc.

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

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

## ◆ TEST() [163/299]

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

Definition at line 1019 of file geometry_unittests.cc.

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

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

## ◆ TEST() [164/299]

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

Definition at line 998 of file geometry_unittests.cc.

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

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

## ◆ TEST() [165/299]

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

Definition at line 2013 of file geometry_unittests.cc.

2013 {
2014 {
2015 std::stringstream stream;
2016 Point m;
2017 stream << m;
2018 ASSERT_EQ(stream.str(), "(0, 0)");
2019 }
2020
2021 {
2022 std::stringstream stream;
2023 Point m(13, 37);
2024 stream << m;
2025 ASSERT_EQ(stream.str(), "(13, 37)");
2026 }
2027 }

## ◆ TEST() [166/299]

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

Definition at line 937 of file geometry_unittests.cc.

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

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

## ◆ TEST() [167/299]

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

Definition at line 1082 of file geometry_unittests.cc.

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

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

## ◆ TEST() [168/299]

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

Definition at line 538 of file geometry_unittests.cc.

538 {
539 auto q1 = Quaternion{{0.0, 0.0, 1.0}, 0.0};
540 auto q2 = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
541
542 auto q3 = q1.Slerp(q2, 0.5);
543
544 auto expected = Quaternion{{0.0, 0.0, 1.0}, kPiOver4 / 2.0};
545
546 ASSERT_QUATERNION_NEAR(q3, expected);
547 }

References ASSERT_QUATERNION_NEAR, and impeller::kPiOver4.

## ◆ TEST() [169/299]

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

Definition at line 549 of file geometry_unittests.cc.

549 {
550 {
551 Quaternion q({0, 0, 1}, 0);
552 Vector3 v(0, 1, 0);
553
554 Vector3 result = q * v;
555 Vector3 expected(0, 1, 0);
556
557 ASSERT_VECTOR3_NEAR(result, expected);
558 }
559
560 {
561 Quaternion q({0, 0, 1}, k2Pi);
562 Vector3 v(1, 0, 0);
563
564 Vector3 result = q * v;
565 Vector3 expected(1, 0, 0);
566
567 ASSERT_VECTOR3_NEAR(result, expected);
568 }
569
570 {
571 Quaternion q({0, 0, 1}, kPiOver4);
572 Vector3 v(0, 1, 0);
573
574 Vector3 result = q * v;
575 Vector3 expected(-k1OverSqrt2, k1OverSqrt2, 0);
576
577 ASSERT_VECTOR3_NEAR(result, expected);
578 }
579
580 {
581 Quaternion q(Vector3(1, 0, 1).Normalize(), kPi);
582 Vector3 v(0, 0, -1);
583
584 Vector3 result = q * v;
585 Vector3 expected(-1, 0, 0);
586
587 ASSERT_VECTOR3_NEAR(result, expected);
588 }
589 }

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

## ◆ TEST() [170/299]

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

Definition at line 1755 of file geometry_unittests.cc.

1755 {
1756 {
1757 // Origin is inclusive
1758 Rect r = Rect::MakeXYWH(100, 100, 100, 100);
1759 Point p(100, 100);
1760 ASSERT_TRUE(r.Contains(p));
1761 }
1762 {
1763 // Size is exclusive
1764 Rect r = Rect::MakeXYWH(100, 100, 100, 100);
1765 Point p(200, 200);
1766 ASSERT_FALSE(r.Contains(p));
1767 }
1768 {
1769 Rect r = Rect::MakeXYWH(100, 100, 100, 100);
1770 Point p(99, 99);
1771 ASSERT_FALSE(r.Contains(p));
1772 }
1773 {
1774 Rect r = Rect::MakeXYWH(100, 100, 100, 100);
1775 Point p(199, 199);
1776 ASSERT_TRUE(r.Contains(p));
1777 }
1778
1779 {
1780 Rect r = Rect::MakeMaximum();
1781 Point p(199, 199);
1782 ASSERT_TRUE(r.Contains(p));
1783 }
1784 }

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

## ◆ TEST() [171/299]

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

Definition at line 1786 of file geometry_unittests.cc.

1786 {
1787 {
1788 Rect a = Rect::MakeXYWH(100, 100, 100, 100);
1789 ASSERT_TRUE(a.Contains(a));
1790 }
1791 {
1792 Rect a = Rect::MakeXYWH(100, 100, 100, 100);
1793 Rect b = Rect::MakeXYWH(0, 0, 0, 0);
1794 ASSERT_FALSE(a.Contains(b));
1795 }
1796 {
1797 Rect a = Rect::MakeXYWH(100, 100, 100, 100);
1798 Rect b = Rect::MakeXYWH(150, 150, 20, 20);
1799 ASSERT_TRUE(a.Contains(b));
1800 }
1801 {
1802 Rect a = Rect::MakeXYWH(100, 100, 100, 100);
1803 Rect b = Rect::MakeXYWH(150, 150, 100, 100);
1804 ASSERT_FALSE(a.Contains(b));
1805 }
1806 {
1807 Rect a = Rect::MakeXYWH(100, 100, 100, 100);
1808 Rect b = Rect::MakeXYWH(50, 50, 100, 100);
1809 ASSERT_FALSE(a.Contains(b));
1810 }
1811 {
1812 Rect a = Rect::MakeXYWH(100, 100, 100, 100);
1813 Rect b = Rect::MakeXYWH(0, 0, 300, 300);
1814 ASSERT_FALSE(a.Contains(b));
1815 }
1816 {
1817 Rect a = Rect::MakeMaximum();
1818 Rect b = Rect::MakeXYWH(0, 0, 300, 300);
1819 ASSERT_TRUE(a.Contains(b));
1820 }
1821 }

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

## ◆ TEST() [172/299]

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

Definition at line 1696 of file geometry_unittests.cc.

1696 {
1697 // No cutout.
1698 {
1699 Rect a = Rect::MakeXYWH(0, 0, 100, 100);
1700 Rect b = Rect::MakeXYWH(0, 0, 50, 50);
1701 auto u = a.Cutout(b);
1702 ASSERT_TRUE(u.has_value());
1703 ASSERT_RECT_NEAR(u.value(), a);
1704 }
1705
1706 // Full cutout.
1707 {
1708 Rect a = Rect::MakeXYWH(0, 0, 100, 100);
1709 Rect b = Rect::MakeXYWH(-10, -10, 120, 120);
1710 auto u = a.Cutout(b);
1711 ASSERT_FALSE(u.has_value());
1712 }
1713
1714 // Cutout from top.
1715 {
1716 auto a = Rect::MakeLTRB(0, 0, 100, 100);
1717 auto b = Rect::MakeLTRB(-10, -10, 110, 90);
1718 auto u = a.Cutout(b);
1719 auto expected = Rect::MakeLTRB(0, 90, 100, 100);
1720 ASSERT_TRUE(u.has_value());
1721 ASSERT_RECT_NEAR(u.value(), expected);
1722 }
1723
1724 // Cutout from bottom.
1725 {
1726 auto a = Rect::MakeLTRB(0, 0, 100, 100);
1727 auto b = Rect::MakeLTRB(-10, 10, 110, 110);
1728 auto u = a.Cutout(b);
1729 auto expected = Rect::MakeLTRB(0, 0, 100, 10);
1730 ASSERT_TRUE(u.has_value());
1731 ASSERT_RECT_NEAR(u.value(), expected);
1732 }
1733
1734 // Cutout from left.
1735 {
1736 auto a = Rect::MakeLTRB(0, 0, 100, 100);
1737 auto b = Rect::MakeLTRB(-10, -10, 90, 110);
1738 auto u = a.Cutout(b);
1739 auto expected = Rect::MakeLTRB(90, 0, 100, 100);
1740 ASSERT_TRUE(u.has_value());
1741 ASSERT_RECT_NEAR(u.value(), expected);
1742 }
1743
1744 // Cutout from right.
1745 {
1746 auto a = Rect::MakeLTRB(0, 0, 100, 100);
1747 auto b = Rect::MakeLTRB(10, -10, 110, 110);
1748 auto u = a.Cutout(b);
1749 auto expected = Rect::MakeLTRB(0, 0, 10, 100);
1750 ASSERT_TRUE(u.has_value());
1751 ASSERT_RECT_NEAR(u.value(), expected);
1752 }
1753 }

References ASSERT_RECT_NEAR, impeller::TRect< T >::Cutout(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [173/299]

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

Definition at line 1946 of file geometry_unittests.cc.

1946 {
1947 auto r = Rect::MakeLTRB(1, 2, 3, 4);
1948
1949 ASSERT_EQ(r.GetLeft(), 1);
1950 ASSERT_EQ(r.GetTop(), 2);
1951 ASSERT_EQ(r.GetRight(), 3);
1952 ASSERT_EQ(r.GetBottom(), 4);
1953
1954 ASSERT_POINT_NEAR(r.GetLeftTop(), Point(1, 2));
1955 ASSERT_POINT_NEAR(r.GetRightTop(), Point(3, 2));
1956 ASSERT_POINT_NEAR(r.GetLeftBottom(), Point(1, 4));
1957 ASSERT_POINT_NEAR(r.GetRightBottom(), Point(3, 4));
1958 }

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

## ◆ TEST() [174/299]

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

Definition at line 1877 of file geometry_unittests.cc.

1877 {
1878 {
1879 auto a = Rect::MakeLTRB(100, 100, 200, 200);
1880 auto b = a.Expand(1);
1881 auto expected = Rect::MakeLTRB(99, 99, 201, 201);
1882 ASSERT_RECT_NEAR(b, expected);
1883 }
1884 {
1885 auto a = Rect::MakeLTRB(100, 100, 200, 200);
1886 auto b = a.Expand(-1);
1887 auto expected = Rect::MakeLTRB(101, 101, 199, 199);
1888 ASSERT_RECT_NEAR(b, expected);
1889 }
1890
1891 {
1892 auto a = Rect::MakeLTRB(100, 100, 200, 200);
1893 auto b = a.Expand(1, 2, 3, 4);
1894 auto expected = Rect::MakeLTRB(99, 98, 203, 204);
1895 ASSERT_RECT_NEAR(b, expected);
1896 }
1897 {
1898 auto a = Rect::MakeLTRB(100, 100, 200, 200);
1899 auto b = a.Expand(-1, -2, -3, -4);
1900 auto expected = Rect::MakeLTRB(101, 102, 197, 196);
1901 ASSERT_RECT_NEAR(b, expected);
1902 }
1903 }

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

## ◆ TEST() [175/299]

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

Definition at line 1823 of file geometry_unittests.cc.

1823 {
1824 {
1825 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
1826 auto points = r.GetPoints();
1827 ASSERT_POINT_NEAR(points[0], Point(100, 200));
1828 ASSERT_POINT_NEAR(points[1], Point(400, 200));
1829 ASSERT_POINT_NEAR(points[2], Point(100, 600));
1830 ASSERT_POINT_NEAR(points[3], Point(400, 600));
1831 }
1832
1833 {
1834 Rect r = Rect::MakeMaximum();
1835 auto points = r.GetPoints();
1836 ASSERT_EQ(points[0], Point(-std::numeric_limits<float>::infinity(),
1837 -std::numeric_limits<float>::infinity()));
1838 ASSERT_EQ(points[1], Point(std::numeric_limits<float>::infinity(),
1839 -std::numeric_limits<float>::infinity()));
1840 ASSERT_EQ(points[2], Point(-std::numeric_limits<float>::infinity(),
1841 std::numeric_limits<float>::infinity()));
1842 ASSERT_EQ(points[3], Point(std::numeric_limits<float>::infinity(),
1843 std::numeric_limits<float>::infinity()));
1844 }
1845 }

References ASSERT_POINT_NEAR, impeller::TRect< T >::GetPoints(), impeller::TRect< Scalar >::MakeMaximum(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [176/299]

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

Definition at line 1905 of file geometry_unittests.cc.

1905 {
1906 {
1907 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
1908 auto actual = r.GetPositive();
1909 ASSERT_RECT_NEAR(r, actual);
1910 }
1911 {
1912 Rect r = Rect::MakeXYWH(100, 200, -100, -100);
1913 auto actual = r.GetPositive();
1914 Rect expected = Rect::MakeXYWH(0, 100, 100, 100);
1915 ASSERT_RECT_NEAR(expected, actual);
1916 }
1917 }

References ASSERT_RECT_NEAR, impeller::TRect< T >::GetPositive(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [177/299]

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

Definition at line 1854 of file geometry_unittests.cc.

1854 {
1855 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
1856 auto points = r.GetTransformedPoints(Matrix::MakeTranslation({10, 20}));
1857 ASSERT_POINT_NEAR(points[0], Point(110, 220));
1858 ASSERT_POINT_NEAR(points[1], Point(410, 220));
1859 ASSERT_POINT_NEAR(points[2], Point(110, 620));
1860 ASSERT_POINT_NEAR(points[3], Point(410, 620));
1861 }

References ASSERT_POINT_NEAR, impeller::TRect< T >::GetTransformedPoints(), impeller::Matrix::MakeTranslation(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [178/299]

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

Definition at line 1555 of file geometry_unittests.cc.

1555 {
1556 {
1557 Rect a = Rect::MakeXYWH(100, 100, 100, 100);
1558 Rect b = Rect::MakeXYWH(0, 0, 0, 0);
1559
1560 auto u = a.Intersection(b);
1561 ASSERT_FALSE(u.has_value());
1562 }
1563
1564 {
1565 Rect a = Rect::MakeXYWH(100, 100, 100, 100);
1566 Rect b = Rect::MakeXYWH(10, 10, 0, 0);
1567 auto u = a.Intersection(b);
1568 ASSERT_FALSE(u.has_value());
1569 }
1570
1571 {
1572 Rect a = Rect::MakeXYWH(0, 0, 100, 100);
1573 Rect b = Rect::MakeXYWH(10, 10, 100, 100);
1574 auto u = a.Intersection(b);
1575 ASSERT_TRUE(u.has_value());
1576 auto expected = Rect::MakeXYWH(10, 10, 90, 90);
1577 ASSERT_RECT_NEAR(u.value(), expected);
1578 }
1579
1580 {
1581 Rect a = Rect::MakeXYWH(0, 0, 100, 100);
1582 Rect b = Rect::MakeXYWH(100, 100, 100, 100);
1583 auto u = a.Intersection(b);
1584 ASSERT_FALSE(u.has_value());
1585 }
1586
1587 {
1588 Rect a = Rect::MakeMaximum();
1589 Rect b = Rect::MakeXYWH(10, 10, 300, 300);
1590 auto u = a.Intersection(b);
1591 ASSERT_TRUE(u);
1592 ASSERT_RECT_NEAR(u.value(), b);
1593 }
1594
1595 {
1596 Rect a = Rect::MakeMaximum();
1597 Rect b = Rect::MakeMaximum();
1598 auto u = a.Intersection(b);
1599 ASSERT_TRUE(u);
1600 ASSERT_EQ(u, Rect::MakeMaximum());
1601 }
1602 }

References ASSERT_RECT_NEAR, impeller::TRect< T >::Intersection(), impeller::TRect< Scalar >::MakeMaximum(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [179/299]

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

Definition at line 1658 of file geometry_unittests.cc.

1658 {
1659 {
1660 Rect a = Rect::MakeXYWH(100, 100, 100, 100);
1661 Rect b = Rect::MakeXYWH(0, 0, 0, 0);
1662 ASSERT_FALSE(a.IntersectsWithRect(b));
1663 }
1664
1665 {
1666 Rect a = Rect::MakeXYWH(100, 100, 100, 100);
1667 Rect b = Rect::MakeXYWH(10, 10, 0, 0);
1668 ASSERT_FALSE(a.IntersectsWithRect(b));
1669 }
1670
1671 {
1672 Rect a = Rect::MakeXYWH(0, 0, 100, 100);
1673 Rect b = Rect::MakeXYWH(10, 10, 100, 100);
1674 ASSERT_TRUE(a.IntersectsWithRect(b));
1675 }
1676
1677 {
1678 Rect a = Rect::MakeXYWH(0, 0, 100, 100);
1679 Rect b = Rect::MakeXYWH(100, 100, 100, 100);
1680 ASSERT_FALSE(a.IntersectsWithRect(b));
1681 }
1682
1683 {
1684 Rect a = Rect::MakeMaximum();
1685 Rect b = Rect::MakeXYWH(10, 10, 100, 100);
1686 ASSERT_TRUE(a.IntersectsWithRect(b));
1687 }
1688
1689 {
1690 Rect a = Rect::MakeMaximum();
1691 Rect b = Rect::MakeMaximum();
1692 ASSERT_TRUE(a.IntersectsWithRect(b));
1693 }
1694 }

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

## ◆ TEST() [180/299]

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

Definition at line 1863 of file geometry_unittests.cc.

1863 {
1864 {
1865 std::vector<Point> points{{1, 5}, {4, -1}, {0, 6}};
1866 Rect r = Rect::MakePointBounds(points.begin(), points.end()).value();
1867 auto expected = Rect::MakeXYWH(0, -1, 4, 7);
1868 ASSERT_RECT_NEAR(r, expected);
1869 }
1870 {
1871 std::vector<Point> points;
1872 std::optional<Rect> r = Rect::MakePointBounds(points.begin(), points.end());
1873 ASSERT_FALSE(r.has_value());
1874 }
1875 }

References ASSERT_RECT_NEAR, impeller::TRect< Scalar >::MakePointBounds(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [181/299]

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

Definition at line 1960 of file geometry_unittests.cc.

1960 {
1961 {
1962 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
1963 auto actual = r.Project(r);
1964 auto expected = Rect::MakeLTRB(0, 0, 1, 1);
1965 ASSERT_RECT_NEAR(expected, actual);
1966 }
1967 {
1968 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
1969 auto actual = r.Project(Rect::MakeLTRB(0, 0, 100, 100));
1970 auto expected = Rect::MakeLTRB(0.5, 0.5, 1, 1);
1971 ASSERT_RECT_NEAR(expected, actual);
1972 }
1973 }

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

## ◆ TEST() [182/299]

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

Definition at line 1975 of file geometry_unittests.cc.

1975 {
1976 {
1977 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
1978 ASSERT_EQ(Rect::RoundOut(r), r);
1979 }
1980 {
1981 auto r = Rect::MakeLTRB(-100.1, -100.1, 100.1, 100.1);
1982 ASSERT_EQ(Rect::RoundOut(r), Rect::MakeLTRB(-101, -101, 101, 101));
1983 }
1984 }

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

## ◆ TEST() [183/299]

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

Definition at line 1919 of file geometry_unittests.cc.

1919 {
1920 {
1921 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
1922 auto actual = r.Scale(0);
1923 auto expected = Rect::MakeLTRB(0, 0, 0, 0);
1924 ASSERT_RECT_NEAR(expected, actual);
1925 }
1926 {
1927 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
1928 auto actual = r.Scale(-2);
1929 auto expected = Rect::MakeLTRB(200, 200, -200, -200);
1930 ASSERT_RECT_NEAR(expected, actual);
1931 }
1932 {
1933 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
1934 auto actual = r.Scale(Point{0, 0});
1935 auto expected = Rect::MakeLTRB(0, 0, 0, 0);
1936 ASSERT_RECT_NEAR(expected, actual);
1937 }
1938 {
1939 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
1940 auto actual = r.Scale(Size{-1, -2});
1941 auto expected = Rect::MakeLTRB(100, 200, -100, -200);
1942 ASSERT_RECT_NEAR(expected, actual);
1943 }
1944 }

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

## ◆ TEST() [184/299]

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

Definition at line 1847 of file geometry_unittests.cc.

1847 {
1848 auto r = Rect::MakeLTRB(0, 0, 100, 100);
1849
1850 ASSERT_EQ(r.Shift(Point(10, 5)), Rect::MakeLTRB(10, 5, 110, 105));
1851 ASSERT_EQ(r.Shift(Point(-10, -5)), Rect::MakeLTRB(-10, -5, 90, 95));
1852 }

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

## ◆ TEST() [185/299]

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

Definition at line 1469 of file geometry_unittests.cc.

1469 {
1470 {
1471 Rect a = Rect::MakeXYWH(100, 100, 100, 100);
1472 Rect b = Rect::MakeXYWH(0, 0, 0, 0);
1473 auto u = a.Union(b);
1474 auto expected = Rect::MakeXYWH(0, 0, 200, 200);
1475 ASSERT_RECT_NEAR(u, expected);
1476 }
1477
1478 {
1479 Rect a = Rect::MakeXYWH(100, 100, 100, 100);
1480 Rect b = Rect::MakeXYWH(10, 10, 0, 0);
1481 auto u = a.Union(b);
1482 auto expected = Rect::MakeXYWH(10, 10, 190, 190);
1483 ASSERT_RECT_NEAR(u, expected);
1484 }
1485
1486 {
1487 Rect a = Rect::MakeXYWH(0, 0, 100, 100);
1488 Rect b = Rect::MakeXYWH(10, 10, 100, 100);
1489 auto u = a.Union(b);
1490 auto expected = Rect::MakeXYWH(0, 0, 110, 110);
1491 ASSERT_RECT_NEAR(u, expected);
1492 }
1493
1494 {
1495 Rect a = Rect::MakeXYWH(0, 0, 100, 100);
1496 Rect b = Rect::MakeXYWH(100, 100, 100, 100);
1497 auto u = a.Union(b);
1498 auto expected = Rect::MakeXYWH(0, 0, 200, 200);
1499 ASSERT_RECT_NEAR(u, expected);
1500 }
1501 }

References ASSERT_RECT_NEAR, impeller::TRect< Scalar >::MakeXYWH(), and impeller::TRect< T >::Union().

## ◆ TEST() [186/299]

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

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

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

Definition at line 762 of file geometry_unittests.cc.

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

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

## ◆ TEST() [189/299]

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

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

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

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

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

Definition at line 2077 of file geometry_unittests.cc.

2077 {
2078 ASSERT_EQ(Color::ToIColor(Color(0, 0, 0, 0)), 0u);
2079 ASSERT_EQ(Color::ToIColor(Color(1.0, 1.0, 1.0, 1.0)), 0xFFFFFFFF);
2080 ASSERT_EQ(Color::ToIColor(Color(0.5, 0.5, 1.0, 1.0)), 0xFF8080FF);
2081 }

References impeller::Color::ToIColor().

## ◆ TEST() [194/299]

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

Definition at line 1068 of file geometry_unittests.cc.

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

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

## ◆ TEST() [195/299]

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

Definition at line 1047 of file geometry_unittests.cc.

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

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

## ◆ TEST() [196/299]

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

Definition at line 1110 of file geometry_unittests.cc.

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

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

## ◆ TEST() [197/299]

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

Definition at line 1026 of file geometry_unittests.cc.

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

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

## ◆ TEST() [198/299]

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

Definition at line 1005 of file geometry_unittests.cc.

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

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

## ◆ TEST() [199/299]

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

Definition at line 2029 of file geometry_unittests.cc.

2029 {
2030 {
2031 std::stringstream stream;
2032 Vector3 m;
2033 stream << m;
2034 ASSERT_EQ(stream.str(), "(0, 0, 0)");
2035 }
2036
2037 {
2038 std::stringstream stream;
2039 Vector3 m(1, 2, 3);
2040 stream << m;
2041 ASSERT_EQ(stream.str(), "(1, 2, 3)");
2042 }
2043 }

## ◆ TEST() [200/299]

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

Definition at line 1089 of file geometry_unittests.cc.

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

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

## ◆ TEST() [201/299]

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

Definition at line 1075 of file geometry_unittests.cc.

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

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

## ◆ TEST() [202/299]

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

Definition at line 1054 of file geometry_unittests.cc.

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

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

## ◆ TEST() [203/299]

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

Definition at line 1117 of file geometry_unittests.cc.

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

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

## ◆ TEST() [204/299]

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

Definition at line 1033 of file geometry_unittests.cc.

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

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

## ◆ TEST() [205/299]

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

Definition at line 1012 of file geometry_unittests.cc.

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

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

## ◆ TEST() [206/299]

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

Definition at line 2045 of file geometry_unittests.cc.

2045 {
2046 {
2047 std::stringstream stream;
2048 Vector4 m;
2049 stream << m;
2050 ASSERT_EQ(stream.str(), "(0, 0, 0, 1)");
2051 }
2052
2053 {
2054 std::stringstream stream;
2055 Vector4 m(1, 2, 3, 4);
2056 stream << m;
2057 ASSERT_EQ(stream.str(), "(1, 2, 3, 4)");
2058 }
2059 }

## ◆ TEST() [207/299]

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

Definition at line 1096 of file geometry_unittests.cc.

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

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

## ◆ TEST() [208/299]

impeller::testing::TEST | ( | HostBufferTest | ,
|  | CanEmplace |
| ) |  |

Definition at line 18 of file host_buffer_unittests.cc.

18 {
19 struct Length2 {
20 uint8_t pad[2];
21 };
22 static_assert(sizeof(Length2) == 2u);
23
24 auto buffer = HostBuffer::Create();
25
26 for (size_t i = 0; i < 12500; i++) {
27 auto view = buffer->Emplace(Length2{});
28 ASSERT_TRUE(view);
29 ASSERT_EQ(buffer->GetLength(), (i + 1) * sizeof(Length2));
30 ASSERT_EQ(view.range, Range(i * sizeof(Length2), 2u));
31 }
32 }

References impeller::HostBuffer::Create().

## ◆ TEST() [209/299]

impeller::testing::TEST | ( | HostBufferTest | ,
|  | CanEmplaceWithAlignment |
| ) |  |

Definition at line 34 of file host_buffer_unittests.cc.

34 {
35 struct Length2 {
36 uint8_t pad[2];
37 };
38 static_assert(sizeof(Length2) == 2);
39 struct alignas(16) Align16 {
40 uint8_t pad[2];
41 };
42 static_assert(alignof(Align16) == 16);
43 static_assert(sizeof(Align16) == 16);
44
45 auto buffer = HostBuffer::Create();
46 ASSERT_TRUE(buffer);
47
48 {
49 auto view = buffer->Emplace(Length2{});
50 ASSERT_TRUE(view);
51 ASSERT_EQ(buffer->GetLength(), 2u);
52 ASSERT_EQ(view.range, Range(0u, 2u));
53 }
54
55 {
56 auto view = buffer->Emplace(Align16{});
57 ASSERT_TRUE(view);
58 ASSERT_EQ(view.range.offset, 16u);
59 ASSERT_EQ(view.range.length, 16u);
60 ASSERT_EQ(buffer->GetLength(), 32u);
61 }
62 {
63 auto view = buffer->Emplace(Length2{});
64 ASSERT_TRUE(view);
65 ASSERT_EQ(buffer->GetLength(), 34u);
66 ASSERT_EQ(view.range, Range(32u, 2u));
67 }
68
69 {
70 auto view = buffer->Emplace(Align16{});
71 ASSERT_TRUE(view);
72 ASSERT_EQ(view.range.offset, 48u);
73 ASSERT_EQ(view.range.length, 16u);
74 ASSERT_EQ(buffer->GetLength(), 64u);
75 }
76 }

References impeller::HostBuffer::Create().

## ◆ TEST() [210/299]

impeller::testing::TEST | ( | HostBufferTest | ,
|  | TestInitialization |
| ) |  |

Definition at line 11 of file host_buffer_unittests.cc.

11 {
12 ASSERT_TRUE(HostBuffer::Create());
13 // Newly allocated buffers don't touch the heap till they have to.
14 ASSERT_EQ(HostBuffer::Create()->GetLength(), 0u);
15 ASSERT_EQ(HostBuffer::Create()->GetSize(), 0u);
16 }

References impeller::HostBuffer::Create().

## ◆ TEST() [211/299]

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

impeller::testing::TEST | ( | PassBindingsCacheTest | ,
|  | bindPipeline |
| ) |  |

Definition at line 26 of file pass_bindings_cache_unittests.cc.

26 {
27 auto context = MockVulkanContextBuilder().Build();
28 PassBindingsCache cache;
29 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
30 auto buffer = encoder->GetCommandBuffer();
31 VkPipeline vk_pipeline = reinterpret_cast<VkPipeline>(0xfeedface);
32 vk::Pipeline pipeline(vk_pipeline);
33 cache.BindPipeline(buffer, vk::PipelineBindPoint::eGraphics, pipeline);
34 cache.BindPipeline(buffer, vk::PipelineBindPoint::eGraphics, pipeline);
35 std::shared_ptr<std::vector<std::string>> functions =
36 GetMockVulkanFunctions(context->GetDevice());
37 EXPECT_EQ(CountStringViewInstances(*functions, "vkCmdBindPipeline"), 1);
38 }

References impeller::PassBindingsCache::BindPipeline().

## ◆ TEST() [213/299]

impeller::testing::TEST | ( | PassBindingsCacheTest | ,
|  | setScissor |
| ) |  |

Definition at line 55 of file pass_bindings_cache_unittests.cc.

55 {
56 auto context = MockVulkanContextBuilder().Build();
57 PassBindingsCache cache;
58 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
59 auto buffer = encoder->GetCommandBuffer();
60 vk::Rect2D scissors;
61 cache.SetScissor(buffer, 0, 1, &scissors);
62 cache.SetScissor(buffer, 0, 1, &scissors);
63 std::shared_ptr<std::vector<std::string>> functions =
64 GetMockVulkanFunctions(context->GetDevice());
65 EXPECT_EQ(CountStringViewInstances(*functions, "vkCmdSetScissor"), 1);
66 }

References impeller::PassBindingsCache::SetScissor().

## ◆ TEST() [214/299]

impeller::testing::TEST | ( | PassBindingsCacheTest | ,
|  | setStencilReference |
| ) |  |

Definition at line 40 of file pass_bindings_cache_unittests.cc.

40 {
41 auto context = MockVulkanContextBuilder().Build();
42 PassBindingsCache cache;
43 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
44 auto buffer = encoder->GetCommandBuffer();
45 cache.SetStencilReference(
46 buffer, vk::StencilFaceFlagBits::eVkStencilFrontAndBack, 123);
47 cache.SetStencilReference(
48 buffer, vk::StencilFaceFlagBits::eVkStencilFrontAndBack, 123);
49 std::shared_ptr<std::vector<std::string>> functions =
50 GetMockVulkanFunctions(context->GetDevice());
51 EXPECT_EQ(CountStringViewInstances(*functions, "vkCmdSetStencilReference"),
52 1);
53 }

References impeller::PassBindingsCache::SetStencilReference().

## ◆ TEST() [215/299]

impeller::testing::TEST | ( | PassBindingsCacheTest | ,
|  | setViewport |
| ) |  |

Definition at line 68 of file pass_bindings_cache_unittests.cc.

68 {
69 auto context = MockVulkanContextBuilder().Build();
70 PassBindingsCache cache;
71 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
72 auto buffer = encoder->GetCommandBuffer();
73 vk::Viewport viewports;
74 cache.SetViewport(buffer, 0, 1, &viewports);
75 cache.SetViewport(buffer, 0, 1, &viewports);
76 std::shared_ptr<std::vector<std::string>> functions =
77 GetMockVulkanFunctions(context->GetDevice());
78 EXPECT_EQ(CountStringViewInstances(*functions, "vkCmdSetViewport"), 1);
79 }

References impeller::PassBindingsCache::SetViewport().

## ◆ TEST() [216/299]

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

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

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::kAbsGeqTwo);
465 auto path_b = path_a.Clone();
466
467 EXPECT_EQ(path_a.GetBoundingBox(), path_b.GetBoundingBox());
468 EXPECT_EQ(path_a.GetFillType(), path_b.GetFillType());
469 EXPECT_EQ(path_a.IsConvex(), path_b.IsConvex());
470
471 auto poly_a = path_a.CreatePolyline(1.0);
472 auto poly_b = path_b.CreatePolyline(1.0);
473
474 ASSERT_EQ(poly_a.points->size(), poly_b.points->size());
475 ASSERT_EQ(poly_a.contours.size(), poly_b.contours.size());
476
477 for (auto i = 0u; i < poly_a.points->size(); i++) {
478 EXPECT_EQ((*poly_a.points)[i], (*poly_b.points)[i]);
479 }
480
481 for (auto i = 0u; i < poly_a.contours.size(); i++) {
482 EXPECT_EQ(poly_a.contours[i].start_index, poly_b.contours[i].start_index);
483 EXPECT_EQ(poly_a.contours[i].start_direction,
484 poly_b.contours[i].start_direction);
485 }
486 }

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

## ◆ TEST() [219/299]

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

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 impeller::CubicPathComponent::AppendPolylinePoints().

## ◆ TEST() [221/299]

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::Path::Polyline::contours, impeller::ContourComponent::destination, impeller::Path::Polyline::points, and impeller::PathBuilder::TakePath().

## ◆ TEST() [222/299]

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

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::Polyline::contours, impeller::Path::CreatePolyline(), impeller::Path::Polyline::GetPoint(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Path::Polyline::points, and impeller::PathBuilder::TakePath().

## ◆ TEST() [224/299]

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

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

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(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [227/299]

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::Path::Polyline::contours, impeller::LineTo(), impeller::MoveTo(), and impeller::Path::Polyline::points.

## ◆ TEST() [228/299]

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

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

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::Path::Polyline::contours, impeller::Path::Polyline::GetPoint(), impeller::LineTo(), impeller::PathBuilder::MoveTo(), and impeller::Path::Polyline::points.

## ◆ TEST() [231/299]

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

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

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(), and impeller::PathBuilder::MoveTo().

## ◆ TEST() [234/299]

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

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::Path::Polyline::GetContourPointBounds(), impeller::LineTo(), and impeller::MoveTo().

## ◆ TEST() [236/299]

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

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

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

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

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

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

Definition at line 495 of file rect_unittests.cc.

495 {
496 auto rect1 =
497 Rect::MakeXYWH(472.599945f, 440.999969f, 1102.80005f, 654.000061f);
498 auto rect2 = Rect::MakeXYWH(724.f, 618.f, 600.f, 300.f);
499 EXPECT_TRUE(rect1.Contains(rect2));
500 }

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

## ◆ TEST() [242/299]

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

Definition at line 434 of file rect_unittests.cc.

434 {
435 EXPECT_EQ(Rect::MakeXYWH(10, 30, 20, 20).GetCenter(), Point(20, 40));
436 EXPECT_EQ(Rect::MakeXYWH(10, 30, 20, 19).GetCenter(), Point(20, 39.5));
437
438 // Note that we expect a Point as the answer from an IRect
439 EXPECT_EQ(IRect::MakeXYWH(10, 30, 20, 20).GetCenter(), Point(20, 40));
440 EXPECT_EQ(IRect::MakeXYWH(10, 30, 20, 19).GetCenter(), Point(20, 39.5));
441 }

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

## ◆ TEST() [243/299]

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

Definition at line 222 of file rect_unittests.cc.

222 {
223 EXPECT_EQ(IRect::MakeXYWH(0, 0, 100, 200).Area(), 20000);
224 EXPECT_EQ(IRect::MakeXYWH(10, 20, 100, 200).Area(), 20000);
225 EXPECT_EQ(IRect::MakeXYWH(0, 0, 200, 100).Area(), 20000);
226 EXPECT_EQ(IRect::MakeXYWH(10, 20, 200, 100).Area(), 20000);
227 EXPECT_EQ(IRect::MakeXYWH(0, 0, 100, 100).Area(), 10000);
228 EXPECT_EQ(IRect::MakeXYWH(10, 20, 100, 100).Area(), 10000);
229 }

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

## ◆ TEST() [244/299]

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

Definition at line 469 of file rect_unittests.cc.

469 {
470 auto rect = IRect::MakeLTRB(100, 100, 200, 200);
471
472 // Expand(T amount)
473 EXPECT_EQ(rect.Expand(10), IRect::MakeLTRB(90, 90, 210, 210));
474 EXPECT_EQ(rect.Expand(-10), IRect::MakeLTRB(110, 110, 190, 190));
475
476 // Expand(amount, amount)
477 EXPECT_EQ(rect.Expand(10, 10), IRect::MakeLTRB(90, 90, 210, 210));
478 EXPECT_EQ(rect.Expand(10, -10), IRect::MakeLTRB(90, 110, 210, 190));
479 EXPECT_EQ(rect.Expand(-10, 10), IRect::MakeLTRB(110, 90, 190, 210));
480 EXPECT_EQ(rect.Expand(-10, -10), IRect::MakeLTRB(110, 110, 190, 190));
481
482 // Expand(IPoint amount)
483 EXPECT_EQ(rect.Expand(IPoint{10, 10}), IRect::MakeLTRB(90, 90, 210, 210));
484 EXPECT_EQ(rect.Expand(IPoint{10, -10}), IRect::MakeLTRB(90, 110, 210, 190));
485 EXPECT_EQ(rect.Expand(IPoint{-10, 10}), IRect::MakeLTRB(110, 90, 190, 210));
486 EXPECT_EQ(rect.Expand(IPoint{-10, -10}), IRect::MakeLTRB(110, 110, 190, 190));
487
488 // Expand(ISize amount)
489 EXPECT_EQ(rect.Expand(ISize{10, 10}), IRect::MakeLTRB(90, 90, 210, 210));
490 EXPECT_EQ(rect.Expand(ISize{10, -10}), IRect::MakeLTRB(90, 110, 210, 190));
491 EXPECT_EQ(rect.Expand(ISize{-10, 10}), IRect::MakeLTRB(110, 90, 190, 210));
492 EXPECT_EQ(rect.Expand(ISize{-10, -10}), IRect::MakeLTRB(110, 110, 190, 190));
493 }

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

## ◆ TEST() [245/299]

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

Definition at line 92 of file rect_unittests.cc.

92 {
93 EXPECT_EQ(IRect(IRect::MakeXYWH(2, 3, 7, 15)), //
94 IRect::MakeXYWH(2, 3, 7, 15));
95 EXPECT_EQ(IRect(IRect::MakeLTRB(2, 3, 7, 15)), //
96 IRect::MakeLTRB(2, 3, 7, 15));
97 }

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

## ◆ TEST() [246/299]

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

Definition at line 80 of file rect_unittests.cc.

80 {
81 EXPECT_EQ(IRect(Rect::MakeXYWH(2, 3, 7, 15)), //
82 IRect::MakeXYWH(2, 3, 7, 15));
83 EXPECT_EQ(IRect(Rect::MakeLTRB(2, 3, 7, 15)), //
84 IRect::MakeLTRB(2, 3, 7, 15));
85
86 EXPECT_EQ(IRect(Rect::MakeXYWH(2.5, 3.5, 7.75, 15.75)),
87 IRect::MakeXYWH(2, 3, 7, 15));
88 EXPECT_EQ(IRect(Rect::MakeLTRB(2.5, 3.5, 7.75, 15.75)),
89 IRect::MakeLTRB(2, 3, 7, 15));
90 }

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

## ◆ TEST() [247/299]

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

Definition at line 319 of file rect_unittests.cc.

319 {
320 {
321 // Checks for expected matrix values
322
323 auto r = IRect::MakeXYWH(100, 200, 200, 400);
324
325 EXPECT_EQ(r.GetNormalizingTransform(),
326 Matrix::MakeScale({0.005, 0.0025, 1.0}) *
327 Matrix::MakeTranslation({-100, -200}));
328 }
329
330 {
331 // Checks for expected transform of points relative to the rect
332
333 auto r = IRect::MakeLTRB(300, 500, 400, 700);
334 auto m = r.GetNormalizingTransform();
335
336 // The 4 corners of the rect => (0, 0) to (1, 1)
337 EXPECT_EQ(m * Point(300, 500), Point(0, 0));
338 EXPECT_EQ(m * Point(400, 500), Point(1, 0));
339 EXPECT_EQ(m * Point(400, 700), Point(1, 1));
340 EXPECT_EQ(m * Point(300, 700), Point(0, 1));
341
342 // The center => (0.5, 0.5)
343 EXPECT_EQ(m * Point(350, 600), Point(0.5, 0.5));
344
345 // Outside the 4 corners => (-1, -1) to (2, 2)
346 EXPECT_EQ(m * Point(200, 300), Point(-1, -1));
347 EXPECT_EQ(m * Point(500, 300), Point(2, -1));
348 EXPECT_EQ(m * Point(500, 900), Point(2, 2));
349 EXPECT_EQ(m * Point(200, 900), Point(-1, 2));
350 }
351
352 {
353 // Checks for behavior with empty rects
354
355 auto zero = Matrix::MakeScale({0.0, 0.0, 1.0});
356
357 // Empty for width and/or height == 0
358 EXPECT_EQ(IRect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
359 EXPECT_EQ(IRect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
360 EXPECT_EQ(IRect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
361
362 // Empty for width and/or height < 0
363 EXPECT_EQ(IRect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
364 EXPECT_EQ(IRect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
365 EXPECT_EQ(IRect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
366 }
367 }

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

## ◆ TEST() [248/299]

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

Definition at line 40 of file rect_unittests.cc.

40 {
41 {
42 IRect r = IRect::MakeOriginSize({10, 20}, {50, 40});
43 EXPECT_EQ(r.GetOrigin(), IPoint(10, 20));
44 EXPECT_EQ(r.GetSize(), ISize(50, 40));
45 EXPECT_EQ(r.GetX(), 10);
46 EXPECT_EQ(r.GetY(), 20);
47 EXPECT_EQ(r.GetWidth(), 50);
48 EXPECT_EQ(r.GetHeight(), 40);
49 auto expected_array = std::array<int64_t, 4>{10, 20, 50, 40};
50 EXPECT_EQ(r.GetXYWH(), expected_array);
51 }
52
53 {
54 IRect r = IRect::MakeLTRB(10, 20, 50, 40);
55 EXPECT_EQ(r.GetOrigin(), IPoint(10, 20));
56 EXPECT_EQ(r.GetSize(), ISize(40, 20));
57 EXPECT_EQ(r.GetX(), 10);
58 EXPECT_EQ(r.GetY(), 20);
59 EXPECT_EQ(r.GetWidth(), 40);
60 EXPECT_EQ(r.GetHeight(), 20);
61 auto expected_array = std::array<int64_t, 4>{10, 20, 40, 20};
62 EXPECT_EQ(r.GetXYWH(), expected_array);
63 }
64 }

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

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

Definition at line 171 of file rect_unittests.cc.

171 {
172 auto test1 = [](IRect rect, int64_t scale) {
173 IRect expected = IRect::MakeXYWH(rect.GetX() * scale, //
174 rect.GetY() * scale, //
175 rect.GetWidth() * scale, //
176 rect.GetHeight() * scale);
177
178 EXPECT_EQ(rect.Scale(scale), expected) //
179 << rect << " * " << scale;
180 EXPECT_EQ(rect.Scale(scale, scale), expected) //
181 << rect << " * " << scale;
182 EXPECT_EQ(rect.Scale(IPoint(scale, scale)), expected) //
183 << rect << " * " << scale;
184 EXPECT_EQ(rect.Scale(ISize(scale, scale)), expected) //
185 << rect << " * " << scale;
186 };
187
188 auto test2 = [&test1](IRect rect, int64_t scale_x, int64_t scale_y) {
189 IRect expected = IRect::MakeXYWH(rect.GetX() * scale_x, //
190 rect.GetY() * scale_y, //
191 rect.GetWidth() * scale_x, //
192 rect.GetHeight() * scale_y);
193
194 EXPECT_EQ(rect.Scale(scale_x, scale_y), expected) //
195 << rect << " * " << scale_x << ", " << scale_y;
196 EXPECT_EQ(rect.Scale(IPoint(scale_x, scale_y)), expected) //
197 << rect << " * " << scale_x << ", " << scale_y;
198 EXPECT_EQ(rect.Scale(ISize(scale_x, scale_y)), expected) //
199 << rect << " * " << scale_x << ", " << scale_y;
200
201 test1(rect, scale_x);
202 test1(rect, scale_y);
203 };
204
205 test2(IRect::MakeLTRB(10, 15, 100, 150), 2, 3);
206 test2(IRect::MakeLTRB(10, 15, 100, 150), 3, 2);
207 test2(IRect::MakeLTRB(10, 15, -100, 150), 2, 3);
208 test2(IRect::MakeLTRB(10, 15, 100, -150), 2, 3);
209 test2(IRect::MakeLTRB(10, 15, 100, 150), -2, 3);
210 test2(IRect::MakeLTRB(10, 15, 100, 150), 2, -3);
211 }

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

## ◆ TEST() [250/299]

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

Definition at line 424 of file rect_unittests.cc.

424 {
425 EXPECT_TRUE(Rect::MakeXYWH(10, 30, 20, 20).IsSquare());
426 EXPECT_FALSE(Rect::MakeXYWH(10, 30, 20, 19).IsSquare());
427 EXPECT_FALSE(Rect::MakeXYWH(10, 30, 19, 20).IsSquare());
428
429 EXPECT_TRUE(IRect::MakeXYWH(10, 30, 20, 20).IsSquare());
430 EXPECT_FALSE(IRect::MakeXYWH(10, 30, 20, 19).IsSquare());
431 EXPECT_FALSE(IRect::MakeXYWH(10, 30, 19, 20).IsSquare());
432 }

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

## ◆ TEST() [251/299]

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

Definition at line 410 of file rect_unittests.cc.

410 {
411 Quad quad = {
412 Point(10, 10),
413 Point(20, 10),
414 Point(10, 20),
415 Point(20, 20),
416 };
417 std::optional<Rect> bounds = Rect::MakePointBounds(quad);
418 EXPECT_TRUE(bounds.has_value());
419 if (bounds.has_value()) {
420 EXPECT_TRUE(RectNear(bounds.value(), Rect::MakeLTRB(10, 10, 20, 20)));
421 }
422 }

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

## ◆ TEST() [252/299]

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

Definition at line 213 of file rect_unittests.cc.

213 {
214 EXPECT_EQ(Rect::MakeXYWH(0, 0, 100, 200).Area(), 20000);
215 EXPECT_EQ(Rect::MakeXYWH(10, 20, 100, 200).Area(), 20000);
216 EXPECT_EQ(Rect::MakeXYWH(0, 0, 200, 100).Area(), 20000);
217 EXPECT_EQ(Rect::MakeXYWH(10, 20, 200, 100).Area(), 20000);
218 EXPECT_EQ(Rect::MakeXYWH(0, 0, 100, 100).Area(), 10000);
219 EXPECT_EQ(Rect::MakeXYWH(10, 20, 100, 100).Area(), 10000);
220 }

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

## ◆ TEST() [253/299]

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

Definition at line 443 of file rect_unittests.cc.

443 {
444 auto rect = Rect::MakeLTRB(100, 100, 200, 200);
445
446 // Expand(T amount)
447 EXPECT_EQ(rect.Expand(10), Rect::MakeLTRB(90, 90, 210, 210));
448 EXPECT_EQ(rect.Expand(-10), Rect::MakeLTRB(110, 110, 190, 190));
449
450 // Expand(amount, amount)
451 EXPECT_EQ(rect.Expand(10, 10), Rect::MakeLTRB(90, 90, 210, 210));
452 EXPECT_EQ(rect.Expand(10, -10), Rect::MakeLTRB(90, 110, 210, 190));
453 EXPECT_EQ(rect.Expand(-10, 10), Rect::MakeLTRB(110, 90, 190, 210));
454 EXPECT_EQ(rect.Expand(-10, -10), Rect::MakeLTRB(110, 110, 190, 190));
455
456 // Expand(Point amount)
457 EXPECT_EQ(rect.Expand(Point{10, 10}), Rect::MakeLTRB(90, 90, 210, 210));
458 EXPECT_EQ(rect.Expand(Point{10, -10}), Rect::MakeLTRB(90, 110, 210, 190));
459 EXPECT_EQ(rect.Expand(Point{-10, 10}), Rect::MakeLTRB(110, 90, 190, 210));
460 EXPECT_EQ(rect.Expand(Point{-10, -10}), Rect::MakeLTRB(110, 110, 190, 190));
461
462 // Expand(Size amount)
463 EXPECT_EQ(rect.Expand(Size{10, 10}), Rect::MakeLTRB(90, 90, 210, 210));
464 EXPECT_EQ(rect.Expand(Size{10, -10}), Rect::MakeLTRB(90, 110, 210, 190));
465 EXPECT_EQ(rect.Expand(Size{-10, 10}), Rect::MakeLTRB(110, 90, 190, 210));
466 EXPECT_EQ(rect.Expand(Size{-10, -10}), Rect::MakeLTRB(110, 110, 190, 190));
467 }

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

## ◆ TEST() [254/299]

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

Definition at line 73 of file rect_unittests.cc.

73 {
74 EXPECT_EQ(Rect(IRect::MakeXYWH(2, 3, 7, 15)),
75 Rect::MakeXYWH(2.0, 3.0, 7.0, 15.0));
76 EXPECT_EQ(Rect(IRect::MakeLTRB(2, 3, 7, 15)),
77 Rect::MakeLTRB(2.0, 3.0, 7.0, 15.0));
78 }

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

## ◆ TEST() [255/299]

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

Definition at line 66 of file rect_unittests.cc.

66 {
67 EXPECT_EQ(Rect(Rect::MakeXYWH(2, 3, 7, 15)),
68 Rect::MakeXYWH(2.0, 3.0, 7.0, 15.0));
69 EXPECT_EQ(Rect(Rect::MakeLTRB(2, 3, 7, 15)),
70 Rect::MakeLTRB(2.0, 3.0, 7.0, 15.0));
71 }

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

## ◆ TEST() [256/299]

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

Definition at line 231 of file rect_unittests.cc.

231 {
232 {
233 // Checks for expected matrix values
234
235 auto r = Rect::MakeXYWH(100, 200, 200, 400);
236
237 EXPECT_EQ(r.GetNormalizingTransform(),
238 Matrix::MakeScale({0.005, 0.0025, 1.0}) *
239 Matrix::MakeTranslation({-100, -200}));
240 }
241
242 {
243 // Checks for expected transform of points relative to the rect
244
245 auto r = Rect::MakeLTRB(300, 500, 400, 700);
246 auto m = r.GetNormalizingTransform();
247
248 // The 4 corners of the rect => (0, 0) to (1, 1)
249 EXPECT_EQ(m * Point(300, 500), Point(0, 0));
250 EXPECT_EQ(m * Point(400, 500), Point(1, 0));
251 EXPECT_EQ(m * Point(400, 700), Point(1, 1));
252 EXPECT_EQ(m * Point(300, 700), Point(0, 1));
253
254 // The center => (0.5, 0.5)
255 EXPECT_EQ(m * Point(350, 600), Point(0.5, 0.5));
256
257 // Outside the 4 corners => (-1, -1) to (2, 2)
258 EXPECT_EQ(m * Point(200, 300), Point(-1, -1));
259 EXPECT_EQ(m * Point(500, 300), Point(2, -1));
260 EXPECT_EQ(m * Point(500, 900), Point(2, 2));
261 EXPECT_EQ(m * Point(200, 900), Point(-1, 2));
262 }
263
264 {
265 // Checks for behavior with empty rects
266
267 auto zero = Matrix::MakeScale({0.0, 0.0, 1.0});
268
269 // Empty for width and/or height == 0
270 EXPECT_EQ(Rect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
271 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
272 EXPECT_EQ(Rect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
273
274 // Empty for width and/or height < 0
275 EXPECT_EQ(Rect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
276 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
277 EXPECT_EQ(Rect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
278 }
279
280 {
281 // Checks for behavior with non-finite rects
282
283 auto z = Matrix::MakeScale({0.0, 0.0, 1.0});
284 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
285 auto inf = std::numeric_limits<Scalar>::infinity();
286
287 // Non-finite for width and/or height == nan
288 EXPECT_EQ(Rect::MakeXYWH(10, 10, nan, 10).GetNormalizingTransform(), z);
289 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, nan).GetNormalizingTransform(), z);
290 EXPECT_EQ(Rect::MakeXYWH(10, 10, nan, nan).GetNormalizingTransform(), z);
291
292 // Non-finite for width and/or height == inf
293 EXPECT_EQ(Rect::MakeXYWH(10, 10, inf, 10).GetNormalizingTransform(), z);
294 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, inf).GetNormalizingTransform(), z);
295 EXPECT_EQ(Rect::MakeXYWH(10, 10, inf, inf).GetNormalizingTransform(), z);
296
297 // Non-finite for width and/or height == -inf
298 EXPECT_EQ(Rect::MakeXYWH(10, 10, -inf, 10).GetNormalizingTransform(), z);
299 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, -inf).GetNormalizingTransform(), z);
300 EXPECT_EQ(Rect::MakeXYWH(10, 10, -inf, -inf).GetNormalizingTransform(), z);
301
302 // Non-finite for origin X and/or Y == nan
303 EXPECT_EQ(Rect::MakeXYWH(nan, 10, 10, 10).GetNormalizingTransform(), z);
304 EXPECT_EQ(Rect::MakeXYWH(10, nan, 10, 10).GetNormalizingTransform(), z);
305 EXPECT_EQ(Rect::MakeXYWH(nan, nan, 10, 10).GetNormalizingTransform(), z);
306
307 // Non-finite for origin X and/or Y == inf
308 EXPECT_EQ(Rect::MakeXYWH(inf, 10, 10, 10).GetNormalizingTransform(), z);
309 EXPECT_EQ(Rect::MakeXYWH(10, inf, 10, 10).GetNormalizingTransform(), z);
310 EXPECT_EQ(Rect::MakeXYWH(inf, inf, 10, 10).GetNormalizingTransform(), z);
311
312 // Non-finite for origin X and/or Y == -inf
313 EXPECT_EQ(Rect::MakeXYWH(-inf, 10, 10, 10).GetNormalizingTransform(), z);
314 EXPECT_EQ(Rect::MakeXYWH(10, -inf, 10, 10).GetNormalizingTransform(), z);
315 EXPECT_EQ(Rect::MakeXYWH(-inf, -inf, 10, 10).GetNormalizingTransform(), z);
316 }
317 }

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

## ◆ TEST() [257/299]

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

Definition at line 99 of file rect_unittests.cc.

99 {
100 {
101 Size s(100, 200);
102 Rect r = Rect::MakeSize(s);
103 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
104 EXPECT_RECT_NEAR(r, expected);
105 }
106
107 {
108 ISize s(100, 200);
109 Rect r = Rect::MakeSize(s);
110 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
111 EXPECT_RECT_NEAR(r, expected);
112 }
113
114 {
115 Size s(100, 200);
116 IRect r = IRect::MakeSize(s);
117 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
118 EXPECT_EQ(r, expected);
119 }
120
121 {
122 ISize s(100, 200);
123 IRect r = IRect::MakeSize(s);
124 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
125 EXPECT_EQ(r, expected);
126 }
127 }

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

## ◆ TEST() [258/299]

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

Definition at line 14 of file rect_unittests.cc.

14 {
15 {
16 Rect r = Rect::MakeOriginSize({10, 20}, {50, 40});
17 EXPECT_EQ(r.GetOrigin(), Point(10, 20));
18 EXPECT_EQ(r.GetSize(), Size(50, 40));
19 EXPECT_EQ(r.GetX(), 10);
20 EXPECT_EQ(r.GetY(), 20);
21 EXPECT_EQ(r.GetWidth(), 50);
22 EXPECT_EQ(r.GetHeight(), 40);
23 auto expected_array = std::array<Scalar, 4>{10, 20, 50, 40};
24 EXPECT_EQ(r.GetXYWH(), expected_array);
25 }
26
27 {
28 Rect r = Rect::MakeLTRB(10, 20, 50, 40);
29 EXPECT_EQ(r.GetOrigin(), Point(10, 20));
30 EXPECT_EQ(r.GetSize(), Size(40, 20));
31 EXPECT_EQ(r.GetX(), 10);
32 EXPECT_EQ(r.GetY(), 20);
33 EXPECT_EQ(r.GetWidth(), 40);
34 EXPECT_EQ(r.GetHeight(), 20);
35 auto expected_array = std::array<Scalar, 4>{10, 20, 40, 20};
36 EXPECT_EQ(r.GetXYWH(), expected_array);
37 }
38 }

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

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

Definition at line 129 of file rect_unittests.cc.

129 {
130 auto test1 = [](Rect rect, Scalar scale) {
131 Rect expected = Rect::MakeXYWH(rect.GetX() * scale, //
132 rect.GetY() * scale, //
133 rect.GetWidth() * scale, //
134 rect.GetHeight() * scale);
135
136 EXPECT_RECT_NEAR(rect.Scale(scale), expected) //
137 << rect << " * " << scale;
138 EXPECT_RECT_NEAR(rect.Scale(scale, scale), expected) //
139 << rect << " * " << scale;
140 EXPECT_RECT_NEAR(rect.Scale(Point(scale, scale)), expected) //
141 << rect << " * " << scale;
142 EXPECT_RECT_NEAR(rect.Scale(Size(scale, scale)), expected) //
143 << rect << " * " << scale;
144 };
145
146 auto test2 = [&test1](Rect rect, Scalar scale_x, Scalar scale_y) {
147 Rect expected = Rect::MakeXYWH(rect.GetX() * scale_x, //
148 rect.GetY() * scale_y, //
149 rect.GetWidth() * scale_x, //
150 rect.GetHeight() * scale_y);
151
152 EXPECT_RECT_NEAR(rect.Scale(scale_x, scale_y), expected) //
153 << rect << " * " << scale_x << ", " << scale_y;
154 EXPECT_RECT_NEAR(rect.Scale(Point(scale_x, scale_y)), expected) //
155 << rect << " * " << scale_x << ", " << scale_y;
156 EXPECT_RECT_NEAR(rect.Scale(Size(scale_x, scale_y)), expected) //
157 << rect << " * " << scale_x << ", " << scale_y;
158
159 test1(rect, scale_x);
160 test1(rect, scale_y);
161 };
162
163 test2(Rect::MakeLTRB(10, 15, 100, 150), 2.5, 3.5);
164 test2(Rect::MakeLTRB(10, 15, 100, 150), 3.5, 2.5);
165 test2(Rect::MakeLTRB(10, 15, -100, 150), 2.5, 3.5);
166 test2(Rect::MakeLTRB(10, 15, 100, -150), 2.5, 3.5);
167 test2(Rect::MakeLTRB(10, 15, 100, 150), -2.5, 3.5);
168 test2(Rect::MakeLTRB(10, 15, 100, 150), 2.5, -3.5);
169 }

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

## ◆ TEST() [260/299]

impeller::testing::TEST | ( | RenderTargetCacheTest | ,
|  | CachesUsedTexturesAcrossFrames |
| ) |  |

Definition at line 45 of file render_target_cache_unittests.cc.

45 {
46 auto allocator = std::make_shared<TestAllocator>();
47 auto render_target_cache = RenderTargetCache(allocator);
48 auto desc = TextureDescriptor{
49 .format = PixelFormat::kR8G8B8A8UNormInt,
50 .size = ISize(100, 100),
51 .usage = static_cast<TextureUsageMask>(TextureUsage::kRenderTarget)};
52
53 render_target_cache.Start();
54 // Create two textures of the same exact size/shape. Both should be marked
55 // as used this frame, so the cached data set will contain two.
56 render_target_cache.CreateTexture(desc);
57 render_target_cache.CreateTexture(desc);
58
59 ASSERT_EQ(render_target_cache.CachedTextureCount(), 2u);
60
61 render_target_cache.End();
62 render_target_cache.Start();
63
64 // Next frame, only create one texture. The set will still contain two,
65 // but one will be removed at the end of the frame.
66 render_target_cache.CreateTexture(desc);
67 ASSERT_EQ(render_target_cache.CachedTextureCount(), 2u);
68
69 render_target_cache.End();
70 ASSERT_EQ(render_target_cache.CachedTextureCount(), 1u);
71 }

References impeller::TextureDescriptor::format, impeller::kR8G8B8A8UNormInt, and impeller::kRenderTarget.

## ◆ TEST() [261/299]

impeller::testing::TEST | ( | RenderTargetCacheTest | ,
|  | DoesNotPersistFailedAllocations |
| ) |  |

Definition at line 73 of file render_target_cache_unittests.cc.

73 {
74 auto allocator = std::make_shared<TestAllocator>();
75 auto render_target_cache = RenderTargetCache(allocator);
76 auto desc = TextureDescriptor{
77 .format = PixelFormat::kR8G8B8A8UNormInt,
78 .size = ISize(100, 100),
79 .usage = static_cast<TextureUsageMask>(TextureUsage::kRenderTarget)};
80
81 render_target_cache.Start();
82 allocator->should_fail = true;
83
84 ASSERT_EQ(render_target_cache.CreateTexture(desc), nullptr);
85 ASSERT_EQ(render_target_cache.CachedTextureCount(), 0u);
86 }

References impeller::TextureDescriptor::format, impeller::kR8G8B8A8UNormInt, and impeller::kRenderTarget.

## ◆ TEST() [262/299]

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::ResourceManagerVK::Create().

## ◆ TEST() [263/299]

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

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

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

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

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

impeller::testing::TEST | ( | SizeTest | ,
|  | IRectIsEmpty |
| ) |  |

Definition at line 393 of file rect_unittests.cc.

393 {
394 // Non-empty
395 EXPECT_FALSE(IRect::MakeXYWH(1, 2, 10, 7).IsEmpty());
396
397 // Empty both width and height both 0 or negative, in all combinations
398 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 0).IsEmpty());
399 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, -1).IsEmpty());
400 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 0).IsEmpty());
401 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, -1).IsEmpty());
402
403 // Empty for 0 or negative width or height (but not both at the same time)
404 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, 0).IsEmpty());
405 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, -1).IsEmpty());
406 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 7).IsEmpty());
407 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 7).IsEmpty());
408 }

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

## ◆ TEST() [269/299]

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

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

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

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

impeller::testing::TEST | ( | SizeTest | ,
|  | RectIsEmpty |
| ) |  |

Definition at line 369 of file rect_unittests.cc.

369 {
370 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
371
372 // Non-empty
373 EXPECT_FALSE(Rect::MakeXYWH(1.5, 2.3, 10.5, 7.2).IsEmpty());
374
375 // Empty both width and height both 0 or negative, in all combinations
376 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 0.0).IsEmpty());
377 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, -1.0).IsEmpty());
378 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, -1.0).IsEmpty());
379 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 0.0).IsEmpty());
380
381 // Empty for 0 or negative width or height (but not both at the same time)
382 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, 0.0).IsEmpty());
383 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, -1.0).IsEmpty());
384 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 7.2).IsEmpty());
385 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 7.2).IsEmpty());
386
387 // Empty for NaN in width or height or both
388 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, nan).IsEmpty());
389 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, 7.2).IsEmpty());
390 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, nan).IsEmpty());
391 }

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

## ◆ TEST() [274/299]

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

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

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

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

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

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

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

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

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

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

Definition at line 72 of file base_unittests.cc.

72 {
73 ASSERT_EQ(SPrintF("%sx%d", "Hello", 12), "Hellox12");
74 ASSERT_EQ(SPrintF(""), "");
75 ASSERT_EQ(SPrintF("Hello"), "Hello");
76 ASSERT_EQ(SPrintF("%sx%.2f", "Hello", 12.122222), "Hellox12.12");
77 }

References impeller::SPrintF().

## ◆ TEST() [284/299]

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

Definition at line 137 of file tessellator_unittests.cc.

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

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

## ◆ TEST() [285/299]

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

Definition at line 173 of file tessellator_unittests.cc.

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

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

## ◆ TEST() [286/299]

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

Definition at line 355 of file tessellator_unittests.cc.

355 {
356 auto tessellator = std::make_shared<Tessellator>();
357
358 auto test = [&tessellator](const Matrix& transform, const Rect& bounds) {
359 auto center = bounds.GetCenter();
360 auto half_size = bounds.GetSize() * 0.5f;
361
362 auto generator = tessellator->FilledEllipse(transform, bounds);
363 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
364
365 auto vertex_count = generator.GetVertexCount();
366 auto vertices = std::vector<Point>();
367 generator.GenerateVertices([&vertices](const Point& p) { //
368 vertices.push_back(p);
369 });
370 EXPECT_EQ(vertices.size(), vertex_count);
371 ASSERT_EQ(vertex_count % 4, 0u);
372
373 auto quadrant_count = vertex_count / 4;
374 for (size_t i = 0; i < quadrant_count; i++) {
375 double angle = kPiOver2 * i / (quadrant_count - 1);
376 double degrees = angle * 180.0 / kPi;
377 double rcos = cos(angle) * half_size.width;
378 double rsin = sin(angle) * half_size.height;
379 EXPECT_POINT_NEAR(vertices[i * 2],
380 Point(center.x - rcos, center.y + rsin))
381 << "vertex " << i << ", angle = " << degrees << ", " //
382 << "bounds = " << bounds << std::endl;
383 EXPECT_POINT_NEAR(vertices[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 - 1],
388 Point(center.x + rcos, center.y - rsin))
389 << "vertex " << i << ", angle = " << degrees << ", " //
390 << "bounds = " << bounds << std::endl;
391 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
392 Point(center.x + rcos, center.y + rsin))
393 << "vertex " << i << ", angle = " << degrees << ", " //
394 << "bounds = " << bounds << std::endl;
395 }
396 };
397
398 // Square bounds should actually use the circle generator, but its
399 // results should match the same math as the ellipse generator.
400 test({}, Rect::MakeXYWH(0, 0, 2, 2));
401
402 test({}, Rect::MakeXYWH(0, 0, 2, 3));
403 test({}, Rect::MakeXYWH(0, 0, 3, 2));
404 test({}, Rect::MakeXYWH(5, 10, 2, 3));
405 test({}, Rect::MakeXYWH(16, 7, 3, 2));
406 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 3, 2));
407 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 2, 3));
408 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
409 Rect::MakeXYWH(5000, 10000, 3000, 2000));
410 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
411 Rect::MakeXYWH(5000, 10000, 2000, 3000));
412 }

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

## ◆ TEST() [287/299]

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

Definition at line 414 of file tessellator_unittests.cc.

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

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

## ◆ TEST() [288/299]

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

Definition at line 284 of file tessellator_unittests.cc.

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

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

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

Definition at line 216 of file tessellator_unittests.cc.

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

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

## ◆ TEST() [290/299]

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

Definition at line 109 of file tessellator_unittests.cc.

109 {
110 {
111 Tessellator t;
112 // Sanity check simple rectangle.
113 auto pts = t.TessellateConvex(
114 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 10, 10)).TakePath(), 1.0);
115
116 std::vector<Point> expected = {
117 {0, 0}, {10, 0}, {0, 10}, {10, 10}, //
118 };
119 EXPECT_EQ(pts, expected);
120 }
121
122 {
123 Tessellator t;
124 auto pts = t.TessellateConvex(PathBuilder{}
125 .AddRect(Rect::MakeLTRB(0, 0, 10, 10))
126 .AddRect(Rect::MakeLTRB(20, 20, 30, 30))
127 .TakePath(),
128 1.0);
129
130 std::vector<Point> expected = {{0, 0}, {10, 0}, {0, 10}, {10, 10},
131 {10, 10}, {20, 20}, {20, 20}, {30, 20},
132 {20, 30}, {30, 30}};
133 EXPECT_EQ(pts, expected);
134 }
135 }

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

## ◆ TEST() [291/299]

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::kPositive);
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::kPositive);
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 =
45 PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath(FillType::kPositive);
46 Tessellator::Result result = t.Tessellate(
47 path, 1.0f,
48 [](const float* vertices, size_t vertices_count,
49 const uint16_t* indices, size_t indices_count) { return true; });
50
51 ASSERT_EQ(result, Tessellator::Result::kSuccess);
52 }
53
54 // Many points.
55 {
56 Tessellator t;
57 PathBuilder builder;
58 for (int i = 0; i < 1000; i++) {
59 auto coord = i * 1.0f;
60 builder.AddLine({coord, coord}, {coord + 1, coord + 1});
61 }
62 auto path = builder.TakePath(FillType::kPositive);
63 Tessellator::Result result = t.Tessellate(
64 path, 1.0f,
65 [](const float* vertices, size_t vertices_count,
66 const uint16_t* indices, size_t indices_count) { return true; });
67
68 ASSERT_EQ(result, Tessellator::Result::kSuccess);
69 }
70
71 // Closure fails.
72 {
73 Tessellator t;
74 auto path =
75 PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath(FillType::kPositive);
76 Tessellator::Result result = t.Tessellate(
77 path, 1.0f,
78 [](const float* vertices, size_t vertices_count,
79 const uint16_t* indices, size_t indices_count) { return false; });
80
81 ASSERT_EQ(result, Tessellator::Result::kInputError);
82 }
83
84 // More than uint16 points, odd fill mode.
85 {
86 Tessellator t;
87 PathBuilder builder = {};
88 for (auto i = 0; i < 1000; i++) {
89 builder.AddCircle(Point(i, i), 4);
90 }
91 auto path = builder.TakePath(FillType::kOdd);
92 bool no_indices = false;
93 size_t count = 0u;
94 Tessellator::Result result = t.Tessellate(
95 path, 1.0f,
96 [&no_indices, &count](const float* vertices, size_t vertices_count,
97 const uint16_t* indices, size_t indices_count) {
98 no_indices = indices == nullptr;
99 count = vertices_count;
100 return true;
101 });
102
103 ASSERT_TRUE(no_indices);
104 ASSERT_TRUE(count >= USHRT_MAX);
105 ASSERT_EQ(result, Tessellator::Result::kSuccess);
106 }
107 }

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

## ◆ TEST() [292/299]

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

impeller::testing::TEST | ( | ThreadTest | ,
|  | CanCreateMutex |
| ) |  |

Definition at line 22 of file base_unittests.cc.

22 {
23 Foo f = {};
24
25 // f.a = 100; <--- Static analysis error.
26 f.mtx.Lock();
27 f.a = 100;
28 f.mtx.Unlock();
29 }

References impeller::testing::Foo::mtx.

## ◆ TEST() [294/299]

impeller::testing::TEST | ( | ThreadTest | ,
|  | CanCreateMutexLock |
| ) |  |

Definition at line 31 of file base_unittests.cc.

31 {
32 Foo f = {};
33
34 // f.a = 100; <--- Static analysis error.
35 auto a = Lock(f.mtx);
36 f.a = 100;
37 }

References impeller::testing::Foo::mtx.

## ◆ TEST() [295/299]

impeller::testing::TEST | ( | ThreadTest | ,
|  | CanCreateRWMutex |
| ) |  |

Definition at line 39 of file base_unittests.cc.

39 {
40 RWFoo f = {};
41
42 // f.a = 100; <--- Static analysis error.
43 f.mtx.LockWriter();
44 f.a = 100;
45 f.mtx.UnlockWriter();
46 // int b = f.a; <--- Static analysis error.
47 f.mtx.LockReader();
48 int b = f.a; // NOLINT(clang-analyzer-deadcode.DeadStores)
49 FML_ALLOW_UNUSED_LOCAL(b);
50 f.mtx.UnlockReader();
51 }

References impeller::testing::RWFoo::mtx.

## ◆ TEST() [296/299]

impeller::testing::TEST | ( | ThreadTest | ,
|  | CanCreateRWMutexLock |
| ) |  |

Definition at line 53 of file base_unittests.cc.

53 {
54 RWFoo f = {};
55
56 // f.a = 100; <--- Static analysis error.
57 {
58 auto write_lock = WriterLock{f.mtx};
59 f.a = 100;
60 }
61
62 // int b = f.a; <--- Static analysis error.
63 {
64 auto read_lock = ReaderLock(f.mtx);
65 int b = f.a; // NOLINT(clang-analyzer-deadcode.DeadStores)
66 FML_ALLOW_UNUSED_LOCAL(b);
67 }
68
69 // f.mtx.UnlockReader(); <--- Static analysis error.
70 }

References impeller::testing::RWFoo::mtx.

## ◆ TEST() [297/299]

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

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

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

impeller::testing::TEST_F | ( | ArchiveTest | ,
|  | AddData |
| ) |  |

Definition at line 122 of file archivist_unittests.cc.

122 {
123 Archive archive(GetArchiveFileName().c_str());
124 ASSERT_TRUE(archive.IsValid());
125 Sample sample;
126 ASSERT_TRUE(archive.Write(sample));
127 }

References impeller::Archive::IsValid(), and impeller::Archive::Write().

## ◆ TEST_F() [2/8]

impeller::testing::TEST_F | ( | ArchiveTest | ,
|  | AddDataMultiple |
| ) |  |

Definition at line 129 of file archivist_unittests.cc.

129 {
130 Archive archive(GetArchiveFileName().c_str());
131 ASSERT_TRUE(archive.IsValid());
132
133 for (size_t i = 0; i < 100; i++) {
134 Sample sample(i + 1);
135 ASSERT_TRUE(archive.Write(sample));
136 }
137 }

References impeller::Archive::IsValid(), and impeller::Archive::Write().

## ◆ TEST_F() [3/8]

impeller::testing::TEST_F | ( | ArchiveTest | ,
|  | AddStorageClass |
| ) |  |

Definition at line 117 of file archivist_unittests.cc.

117 {
118 Archive archive(GetArchiveFileName().c_str());
119 ASSERT_TRUE(archive.IsValid());
120 }

References impeller::Archive::IsValid().

## ◆ TEST_F() [4/8]

impeller::testing::TEST_F | ( | ArchiveTest | ,
|  | CanReadWriteVectorOfArchivables |
| ) |  |

Definition at line 189 of file archivist_unittests.cc.

189 {
190 Archive archive(GetArchiveFileName().c_str());
191 ASSERT_TRUE(archive.IsValid());
192
193 SampleWithVector sample_with_vector;
194 ASSERT_TRUE(archive.Write(sample_with_vector));
195 bool read_success = false;
196 ASSERT_EQ(
197 archive.Read<SampleWithVector>([&](ArchiveLocation& location) -> bool {
198 SampleWithVector other_sample_with_vector;
199 read_success = other_sample_with_vector.Read(location);
200 return true; // Always keep continuing but assert that we only get one.
201 }),
202 1u);
203 ASSERT_TRUE(read_success);
204 }

References impeller::Archive::IsValid(), impeller::Archive::Read(), and impeller::Archive::Write().

## ◆ TEST_F() [5/8]

impeller::testing::TEST_F | ( | ArchiveTest | ,
|  | ReadData |
| ) |  |

Definition at line 139 of file archivist_unittests.cc.

139 {
140 Archive archive(GetArchiveFileName().c_str());
141 ASSERT_TRUE(archive.IsValid());
142
143 size_t count = 50;
144
145 std::vector<PrimaryKey::value_type> keys;
146 std::vector<uint64_t> values;
147
148 for (size_t i = 0; i < count; i++) {
149 Sample sample(i + 1);
150 keys.push_back(sample.GetPrimaryKey().value());
151 values.push_back(sample.GetSomeData());
152 ASSERT_TRUE(archive.Write(sample));
153 }
154
155 for (size_t i = 0; i < count; i++) {
156 Sample sample;
157 ASSERT_TRUE(archive.Read(keys[i], sample));
158 ASSERT_EQ(values[i], sample.GetSomeData());
159 }
160 }

References impeller::testing::Sample::GetPrimaryKey(), impeller::testing::Sample::GetSomeData(), impeller::Archive::IsValid(), impeller::Archive::Read(), and impeller::Archive::Write().

## ◆ TEST_F() [6/8]

impeller::testing::TEST_F | ( | ArchiveTest | ,
|  | ReadDataWithNames |
| ) |  |

Definition at line 162 of file archivist_unittests.cc.

162 {
163 Archive archive(GetArchiveFileName().c_str());
164 ASSERT_TRUE(archive.IsValid());
165
166 size_t count = 8;
167
168 std::vector<PrimaryKey::value_type> keys;
169 std::vector<uint64_t> values;
170
171 keys.reserve(count);
172 values.reserve(count);
173
174 for (size_t i = 0; i < count; i++) {
175 Sample sample(i + 1);
176 keys.push_back(sample.GetPrimaryKey().value());
177 values.push_back(sample.GetSomeData());
178 ASSERT_TRUE(archive.Write(sample));
179 }
180
181 for (size_t i = 0; i < count; i++) {
182 Sample sample;
183 ASSERT_TRUE(archive.Read(keys[i], sample));
184 ASSERT_EQ(values[i], sample.GetSomeData());
185 ASSERT_EQ(keys[i], sample.GetPrimaryKey());
186 }
187 }

References impeller::testing::Sample::GetPrimaryKey(), impeller::testing::Sample::GetSomeData(), impeller::Archive::IsValid(), impeller::Archive::Read(), and impeller::Archive::Write().

## ◆ TEST_F() [7/8]

impeller::testing::TEST_F | ( | ArchiveTest | ,
|  | SimpleInitialization |
| ) |  |

Definition at line 112 of file archivist_unittests.cc.

112 {
113 Archive archive(GetArchiveFileName().c_str());
114 ASSERT_TRUE(archive.IsValid());
115 }

References impeller::Archive::IsValid().

## ◆ TEST_F() [8/8]

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

## ◆ TEST_P() [1/384]

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

Definition at line 359 of file aiks_path_unittests.cc.

359 {
360 Canvas canvas;
361 canvas.Scale(GetContentScale());
362
363 Paint paint;
364 paint.color = Color::Red();
365 std::vector<Color> colors = {Color{1.0, 0.0, 0.0, 1.0},
366 Color{0.0, 0.0, 0.0, 1.0}};
367 std::vector<Scalar> stops = {0.0, 1.0};
368 paint.color_source = ColorSource::MakeSweepGradient(
369 {100, 100}, Degrees(45), Degrees(135), std::move(colors),
370 std::move(stops), Entity::TileMode::kMirror, {});
371 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
372 .style = FilterContents::BlurStyle::kNormal,
373 .sigma = Sigma(20),
374 };
375
376 PathBuilder builder;
377 builder.AddArc(Rect::MakeXYWH(10, 10, 100, 100), Degrees(0), Degrees(0),
378 false);
379 canvas.DrawPath(builder.TakePath(), paint);
380
381 // Check that this empty picture can be created without crashing.
382 canvas.EndRecordingAsPicture();
383 }

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

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

Definition at line 490 of file aiks_unittests.cc.

490 {
491 Canvas canvas;
492 Paint paint;
493
494 paint.color = Color::Red();
495 canvas.DrawPaint(paint);
496
497 paint.blend_mode = BlendMode::kSourceOver;
498 canvas.SaveLayer(paint);
499
500 paint.color = Color::White();
501 canvas.DrawRect(Rect::MakeXYWH(100, 100, 400, 400), paint);
502
503 paint.blend_mode = BlendMode::kSource;
504 canvas.SaveLayer(paint);
505
506 paint.color = Color::Blue();
507 canvas.DrawRect(Rect::MakeXYWH(200, 200, 200, 200), paint);
508
509 canvas.Restore();
510 canvas.Restore();
511
512 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
513 }

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

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

Definition at line 3458 of file aiks_unittests.cc.

3458 {
3459 Canvas canvas;
3460 canvas.Scale(GetContentScale());
3461 canvas.DrawPaint({});
3462 Paint blur = {
3463 .color = Color::Green(),
3464 .mask_blur_descriptor =
3465 Paint::MaskBlurDescriptor{
3466 .style = FilterContents::BlurStyle::kNormal,
3467 .sigma = Sigma(47.6),
3468 },
3469 };
3470 canvas.DrawRect(Rect::MakeXYWH(300, 300, 200, 200), blur);
3471 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3472 }

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

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

Definition at line 3495 of file aiks_unittests.cc.

3495 {
3496 Canvas canvas;
3497 canvas.Scale(GetContentScale());
3498
3499 auto paint_lines = [&canvas](Scalar dx, Scalar dy, Paint paint) {
3500 auto draw_line = [&canvas, &paint](Point a, Point b) {
3501 canvas.DrawPath(PathBuilder{}.AddLine(a, b).TakePath(), paint);
3502 };
3503 paint.stroke_width = 5;
3504 paint.style = Paint::Style::kStroke;
3505 draw_line(Point(dx + 100, dy + 100), Point(dx + 200, dy + 200));
3506 draw_line(Point(dx + 100, dy + 200), Point(dx + 200, dy + 100));
3507 draw_line(Point(dx + 150, dy + 100), Point(dx + 200, dy + 150));
3508 draw_line(Point(dx + 100, dy + 150), Point(dx + 150, dy + 200));
3509 };
3510
3511 AiksContext renderer(GetContext(), nullptr);
3512 Canvas recorder_canvas;
3513 for (int x = 0; x < 5; ++x) {
3514 for (int y = 0; y < 5; ++y) {
3515 Rect rect = Rect::MakeXYWH(x * 20, y * 20, 20, 20);
3516 Paint paint{.color =
3517 ((x + y) & 1) == 0 ? Color::Yellow() : Color::Blue()};
3518 recorder_canvas.DrawRect(rect, paint);
3519 }
3520 }
3521 Picture picture = recorder_canvas.EndRecordingAsPicture();
3522 std::shared_ptr<Texture> texture =
3523 picture.ToImage(renderer, ISize{100, 100})->GetTexture();
3524
3525 ColorSource image_source = ColorSource::MakeImage(
3526 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {}, {});
3527 std::shared_ptr<ImageFilter> blur_filter = ImageFilter::MakeBlur(
3528 Sigma(5), Sigma(5), FilterContents::BlurStyle::kNormal,
3529 Entity::TileMode::kDecal);
3530 canvas.DrawRect(Rect::MakeLTRB(0, 0, 300, 600),
3531 Paint{.color = Color::DarkGreen()});
3532 canvas.DrawRect(Rect::MakeLTRB(100, 100, 200, 200),
3533 Paint{.color_source = image_source});
3534 canvas.DrawRect(Rect::MakeLTRB(300, 0, 600, 600),
3535 Paint{.color = Color::Red()});
3536 canvas.DrawRect(
3537 Rect::MakeLTRB(400, 100, 500, 200),
3538 Paint{.color_source = image_source, .image_filter = blur_filter});
3539 paint_lines(0, 300, Paint{.color_source = image_source});
3540 paint_lines(300, 300,
3541 Paint{.color_source = image_source, .image_filter = blur_filter});
3542 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3543 }

References impeller::PathBuilder::AddLine(), 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::Paint::stroke_width, impeller::Paint::style, impeller::PathBuilder::TakePath(), impeller::Picture::ToImage(), and impeller::Color::Yellow().

## ◆ TEST_P() [5/384]

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

Definition at line 2996 of file aiks_unittests.cc.

2996 {
2997 Canvas subcanvas;
2998 subcanvas.DrawRect(Rect::MakeLTRB(-100, -50, 100, 50),
2999 {.color = Color::CornflowerBlue()});
3000 auto picture = subcanvas.EndRecordingAsPicture();
3001
3002 Canvas canvas;
3003 canvas.Translate({200, 200});
3004 canvas.Rotate(Radians(kPi / 4));
3005 canvas.DrawPicture(picture);
3006
3007 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3008 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPicture(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kPi, impeller::TRect< Scalar >::MakeLTRB(), impeller::Canvas::Rotate(), and impeller::Canvas::Translate().

## ◆ TEST_P() [6/384]

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

Definition at line 3010 of file aiks_unittests.cc.

3010 {
3011 Canvas subcanvas;
3012 subcanvas.DrawRect(
3013 Rect::MakeLTRB(-100, -50, 100, 50),
3014 {.color = Color::CornflowerBlue(), .blend_mode = BlendMode::kColorDodge});
3015 auto picture = subcanvas.EndRecordingAsPicture();
3016
3017 Canvas canvas;
3018 canvas.DrawPaint({.color = Color::Black()});
3019 canvas.DrawCircle(Point::MakeXY(150, 150), 25, {.color = Color::Red()});
3020 canvas.DrawPicture(picture);
3021
3022 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3023 }

References impeller::Color::Black(), impeller::Color::CornflowerBlue(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPicture(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kColorDodge, impeller::TRect< Scalar >::MakeLTRB(), impeller::TPoint< Scalar >::MakeXY(), and impeller::Color::Red().

## ◆ TEST_P() [7/384]

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

Definition at line 3025 of file aiks_unittests.cc.

3025 {
3026 Canvas subcanvas;
3027 subcanvas.SaveLayer({}, {},
3028 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
3029 FilterContents::BlurStyle::kNormal,
3030 Entity::TileMode::kDecal));
3031 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
3032 Paint paint;
3033 paint.color = Color::Red().WithAlpha(0.5);
3034 subcanvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
3035
3036 auto picture = subcanvas.EndRecordingAsPicture();
3037
3038 Canvas canvas;
3039 canvas.DrawPaint({.color = Color::Black()});
3040 canvas.DrawCircle(Point::MakeXY(150, 150), 25, {.color = Color::Red()});
3041 canvas.DrawPicture(picture);
3042
3043 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3044 }

References impeller::Color::Black(), impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawImage(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPicture(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::TPoint< Scalar >::MakeXY(), impeller::Color::Red(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [8/384]

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

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

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

Definition at line 339 of file aiks_path_unittests.cc.

339 {
340 PathBuilder builder = {};
341 for (auto i = 0; i < 10; i++) {
342 if (i % 2 == 0) {
343 builder.AddCircle(Point(100 + 50 * i, 100 + 50 * i), 100);
344 } else {
345 builder.MoveTo({100.f + 50.f * i - 100, 100.f + 50.f * i});
346 builder.LineTo({100.f + 50.f * i, 100.f + 50.f * i - 100});
347 builder.LineTo({100.f + 50.f * i - 100, 100.f + 50.f * i - 100});
348 builder.Close();
349 }
350 }
351 builder.SetConvexity(Convexity::kConvex);
352
353 Canvas canvas;
354 canvas.DrawPath(builder.TakePath(), {.color = Color::Red().WithAlpha(0.4)});
355
356 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
357 }

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

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

Definition at line 939 of file aiks_unittests.cc.

939 {
940 Canvas canvas;
941 canvas.Scale(Vector2(0.2, 0.2));
942 canvas.DrawPaint({.color = Color::MediumTurquoise()});
943 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
944 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::MediumTurquoise(), and impeller::Canvas::Scale().

## ◆ TEST_P() [12/384]

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

Definition at line 946 of file aiks_unittests.cc.

946 {
947 Canvas canvas;
948 canvas.Scale(Vector2(0.2, 0.2));
949 canvas.DrawPaint({.color = Color::MediumTurquoise()});
950 canvas.DrawPaint({.color = Color::Color::OrangeRed().WithAlpha(0.5)});
951 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
952 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::MediumTurquoise(), and impeller::Canvas::Scale().

## ◆ TEST_P() [13/384]

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

Definition at line 1024 of file aiks_unittests.cc.

1024 {
1025 auto modes = GetBlendModeSelection();
1026
1027 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1028 static Color background = Color::MediumTurquoise();
1029 static Color foreground = Color::Color::OrangeRed().WithAlpha(0.5);
1030 static int current_blend_index = 3;
1031
1032 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1033 {
1034 ImGui::ColorEdit4("Background", reinterpret_cast<float*>(&background));
1035 ImGui::ColorEdit4("Foreground", reinterpret_cast<float*>(&foreground));
1036 ImGui::ListBox("Blend mode", &current_blend_index,
1037 modes.blend_mode_names.data(),
1038 modes.blend_mode_names.size());
1039 }
1040 ImGui::End();
1041
1042 Canvas canvas;
1043 canvas.Scale(Vector2(0.2, 0.2));
1044 canvas.DrawPaint({.color = background});
1045 canvas.DrawPaint(
1046 {.color = foreground,
1047 .blend_mode = static_cast<BlendMode>(current_blend_index)});
1048 return canvas.EndRecordingAsPicture();
1049 };
1050 ASSERT_TRUE(OpenPlaygroundHere(callback));
1051 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), GetBlendModeSelection(), impeller::Color::MediumTurquoise(), impeller::Canvas::Scale(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [14/384]

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

Definition at line 954 of file aiks_unittests.cc.

954 {
955 Canvas canvas;
956 canvas.Scale(Vector2(0.2, 0.2));
957 canvas.DrawPaint({.color = Color::MediumTurquoise()});
958 canvas.DrawPaint({.color = Color::Color::OrangeRed().WithAlpha(0.5),
959 .blend_mode = BlendMode::kHue});
960 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
961 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kHue, impeller::Color::MediumTurquoise(), and impeller::Canvas::Scale().

## ◆ TEST_P() [15/384]

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

Definition at line 2836 of file aiks_unittests.cc.

2836 {
2837 std::vector<Point> points = {
2838 {0, 0}, //
2839 {100, 100}, //
2840 {100, 0}, //
2841 {0, 100}, //
2842 {0, 0}, //
2843 {48, 48}, //
2844 {52, 52}, //
2845 };
2846 std::vector<PointStyle> caps = {
2847 PointStyle::kRound,
2848 PointStyle::kSquare,
2849 };
2850 Paint paint;
2851 paint.color = Color::Yellow().WithAlpha(0.5);
2852
2853 Paint background;
2854 background.color = Color::Black();
2855
2856 Canvas canvas;
2857 canvas.DrawPaint(background);
2858 canvas.Translate({200, 200});
2859 canvas.DrawPoints(points, 10, paint, PointStyle::kRound);
2860 canvas.Translate({150, 0});
2861 canvas.DrawPoints(points, 10, paint, PointStyle::kSquare);
2862
2863 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2864 }

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

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

Definition at line 2930 of file aiks_unittests.cc.

2930 {
2931 auto texture = CreateTextureForFixture("table_mountain_nx.png",
2932 /*enable_mipmapping=*/true);
2933
2934 std::vector<Point> points = {
2935 {0, 0}, //
2936 {100, 100}, //
2937 {100, 0}, //
2938 {0, 100}, //
2939 {0, 0}, //
2940 {48, 48}, //
2941 {52, 52}, //
2942 };
2943 std::vector<PointStyle> caps = {
2944 PointStyle::kRound,
2945 PointStyle::kSquare,
2946 };
2947 Paint paint;
2948 paint.color_source = ColorSource::MakeImage(texture, Entity::TileMode::kClamp,
2949 Entity::TileMode::kClamp, {}, {});
2950
2951 Canvas canvas;
2952 canvas.Translate({200, 200});
2953 canvas.DrawPoints(points, 100, paint, PointStyle::kRound);
2954 canvas.Translate({150, 0});
2955 canvas.DrawPoints(points, 100, paint, PointStyle::kSquare);
2956
2957 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2958 }

References impeller::Paint::color_source, impeller::Entity::kClamp, impeller::kRound, impeller::kSquare, impeller::ColorSource::MakeImage(), and impeller::Canvas::Translate().

## ◆ TEST_P() [17/384]

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

Definition at line 580 of file aiks_unittests.cc.

580 {
581 Canvas canvas;
582
583 Paint red;
584 red.color = Color::Red();
585
586 canvas.DrawCircle({250, 250}, 125, red);
587
588 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
589 }

References impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Color::Red().

## ◆ TEST_P() [18/384]

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

Definition at line 603 of file aiks_unittests.cc.

603 {
604 Canvas canvas;
605
606 Paint red;
607 red.color = Color::Red();
608
609 Paint green;
610 green.color = Color::Green();
611
612 Paint blue;
613 blue.color = Color::Blue();
614
615 Paint save;
616 save.color = Color::Black();
617
618 canvas.SaveLayer(save, Rect::MakeXYWH(0, 0, 50, 50));
619
620 canvas.DrawRect(Rect::MakeXYWH(0, 0, 100, 100), red);
621 canvas.DrawRect(Rect::MakeXYWH(10, 10, 100, 100), green);
622 canvas.DrawRect(Rect::MakeXYWH(20, 20, 100, 100), blue);
623
624 canvas.Restore();
625
626 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
627 }

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

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

Definition at line 629 of file aiks_unittests.cc.

630 {
631 Canvas canvas;
632
633 Paint red;
634 red.color = Color::Red();
635
636 Paint green;
637 green.color = Color::Green();
638
639 Paint blue;
640 blue.color = Color::Blue();
641
642 Paint save;
643 save.color = Color::Black().WithAlpha(0.5);
644
645 canvas.SaveLayer(save, Rect::MakeXYWH(0, 0, 100000, 100000));
646
647 canvas.DrawRect(Rect::MakeXYWH(0, 0, 100, 100), red);
648 canvas.DrawRect(Rect::MakeXYWH(10, 10, 100, 100), green);
649 canvas.DrawRect(Rect::MakeXYWH(20, 20, 100, 100), blue);
650
651 canvas.Restore();
652
653 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
654 }

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

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

Definition at line 591 of file aiks_unittests.cc.

591 {
592 Canvas canvas;
593
594 Paint red;
595 red.color = Color::Red();
596
597 canvas.Skew(2, 5);
598 canvas.DrawRect(Rect::MakeXYWH(0, 0, 100, 100), red);
599
600 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
601 }

References impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), and impeller::Canvas::Skew().

## ◆ TEST_P() [21/384]

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

Definition at line 467 of file aiks_unittests.cc.

467 {
468 Canvas recorder_canvas;
469 Paint paint;
470 paint.color = Color{0.9568, 0.2627, 0.2118, 1.0};
471 recorder_canvas.DrawRect(Rect::MakeXYWH(100.0, 100.0, 600, 600), paint);
472 paint.color = Color{0.1294, 0.5882, 0.9529, 1.0};
473 recorder_canvas.DrawRect(Rect::MakeXYWH(200.0, 200.0, 600, 600), paint);
474
475 Canvas canvas;
476 AiksContext renderer(GetContext(), nullptr);
477 paint.color = Color::BlackTransparent();
478 canvas.DrawPaint(paint);
479 Picture picture = recorder_canvas.EndRecordingAsPicture();
480 auto image = picture.ToImage(renderer, ISize{1000, 1000});
481 if (image) {
482 canvas.DrawImage(image, Point(), Paint());
483 paint.color = Color{0.1, 0.1, 0.1, 0.2};
484 canvas.DrawRect(Rect::MakeSize(ISize{1000, 1000}), paint);
485 }
486
487 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
488 }

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

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

Definition at line 2680 of file aiks_unittests.cc.

2680 {
2681 Canvas canvas;
2682 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
2683 canvas.DrawCircle({300, 200}, 100, {.color = Color::GreenYellow()});
2684 canvas.DrawCircle({140, 170}, 75, {.color = Color::DarkMagenta()});
2685 canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
2686 canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), {20, 20});
2687 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
2688 ImageFilter::MakeBlur(Sigma(30.0), Sigma(30.0),
2689 FilterContents::BlurStyle::kNormal,
2690 Entity::TileMode::kClamp));
2691 canvas.Restore();
2692
2693 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2694 }

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

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

Definition at line 2696 of file aiks_unittests.cc.

2696 {
2697 Canvas canvas;
2698 canvas.DrawCircle({400, 400}, 300, {.color = Color::Green()});
2699 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
2700 ImageFilter::MakeBlur(Sigma(999999), Sigma(999999),
2701 FilterContents::BlurStyle::kNormal,
2702 Entity::TileMode::kClamp));
2703 canvas.Restore();
2704
2705 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2706 }

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

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

Definition at line 2657 of file aiks_unittests.cc.

2657 {
2658 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
2659 auto [a, b] = IMPELLER_PLAYGROUND_LINE(Point(50, 50), Point(300, 200), 30,
2660 Color::White(), Color::White());
2661
2662 Canvas canvas;
2663 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
2664 canvas.DrawCircle({300, 200}, 100, {.color = Color::GreenYellow()});
2665 canvas.DrawCircle({140, 170}, 75, {.color = Color::DarkMagenta()});
2666 canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
2667 canvas.ClipRRect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), {20, 20});
2668 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
2669 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
2670 FilterContents::BlurStyle::kNormal,
2671 Entity::TileMode::kClamp));
2672 canvas.Restore();
2673
2674 return canvas.EndRecordingAsPicture();
2675 };
2676
2677 ASSERT_TRUE(OpenPlaygroundHere(callback));
2678 }

References impeller::Canvas::ClipRRect(), impeller::Color::CornflowerBlue(), impeller::Color::DarkMagenta(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::GreenYellow(), IMPELLER_PLAYGROUND_LINE, 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/384]

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

Definition at line 2708 of file aiks_unittests.cc.

2708 {
2709 Canvas canvas;
2710 canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
2711 canvas.DrawCircle(
2712 {400, 400}, 200,
2713 {
2714 .color = Color::Green(),
2715 .image_filter = ImageFilter::MakeBlur(
2716 Sigma(20.0), Sigma(20.0), FilterContents::BlurStyle::kNormal,
2717 Entity::TileMode::kClamp),
2718 });
2719 canvas.Restore();
2720
2721 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2722 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Canvas::Restore().

## ◆ TEST_P() [26/384]

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

Definition at line 1766 of file aiks_unittests.cc.

1766 {
1767 Canvas canvas;
1768
1769 canvas.DrawPaint({.color = Color::White()});
1770
1771 // Draw a green circle on the screen.
1772 {
1773 // Increase the clip depth for the savelayer to contend with.
1774 canvas.ClipPath(PathBuilder{}.AddCircle({100, 100}, 50).TakePath());
1775
1776 canvas.SaveLayer({}, Rect::MakeXYWH(50, 50, 100, 100));
1777
1778 // Fill the layer with white.
1779 canvas.DrawRect(Rect::MakeSize(Size{400, 400}), {.color = Color::White()});
1780 // Fill the layer with green, but do so with a color blend that can't be
1781 // collapsed into the parent pass.
1782 // TODO(jonahwilliams): this blend mode was changed from color burn to
1783 // hardlight to work around https://github.com/flutter/flutter/issues/136554
1784 // .
1785 canvas.DrawRect(
1786 Rect::MakeSize(Size{400, 400}),
1787 {.color = Color::Green(), .blend_mode = BlendMode::kHardLight});
1788 }
1789
1790 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1791 }

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

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

Definition at line 2767 of file aiks_unittests.cc.

2767 {
2768 if (!BackendSupportsFragmentProgram()) {
2769 GTEST_SKIP_("This backend doesn't support runtime effects.");
2770 }
2771
2772 auto runtime_stages =
2773 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2774
2775 auto runtime_stage =
2776 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2777 ASSERT_TRUE(runtime_stage);
2778 ASSERT_TRUE(runtime_stage->IsDirty());
2779
2780 struct FragUniforms {
2781 Vector2 iResolution;
2782 Scalar iTime;
2783 } frag_uniforms = {.iResolution = Vector2(400, 400), .iTime = 100.0};
2784 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2785 uniform_data->resize(sizeof(FragUniforms));
2786 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2787
2788 std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
2789
2790 Paint paint;
2791 paint.color_source = ColorSource::MakeRuntimeEffect(
2792 runtime_stage, uniform_data, texture_inputs);
2793
2794 Canvas canvas;
2795 canvas.Save();
2796 canvas.ClipRRect(Rect::MakeXYWH(0, 0, 400, 400), {10.0, 10.0},
2797 Entity::ClipOperation::kIntersect);
2798 canvas.DrawRect(Rect::MakeXYWH(0, 0, 400, 400), paint);
2799 canvas.Restore();
2800
2801 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2802 }

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

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

Definition at line 385 of file aiks_path_unittests.cc.

385 {
386 Canvas canvas;
387 Paint paint;
388 paint.color = Color::Fuchsia();
389 canvas.ClipPath(
390 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 500, 500)).TakePath());
391 canvas.DrawPath(PathBuilder{}.AddCircle({500, 500}, 250).TakePath(), paint);
392 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
393 }

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

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

Definition at line 81 of file aiks_unittests.cc.

81 {
82 Canvas canvas;
83 Paint paint;
84 paint.color = Color::Blue();
85 canvas.DrawPath(PathBuilder{}
86 .AddRect(Rect::MakeXYWH(100.0, 100.0, 100.0, 100.0))
87 .TakePath(),
88 paint);
89 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
90 }

References impeller::PathBuilder::AddRect(), impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [30/384]

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

Definition at line 114 of file aiks_unittests.cc.

114 {
115 Canvas canvas;
116 Paint paint;
117 paint.color = Color::Red();
118 paint.color_filter =
119 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow());
120 paint.invert_colors = true;
121
122 canvas.DrawRect(Rect::MakeLTRB(0, 0, 100, 100), paint);
123 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
124 }

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

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

Definition at line 126 of file aiks_unittests.cc.

126 {
127 Canvas canvas;
128 Paint paint;
129 paint.color = Color::Red();
130 paint.color_filter =
131 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow());
132 paint.invert_colors = true;
133
134 canvas.DrawPaint(paint);
135 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
136 }

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

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

Definition at line 559 of file aiks_gradient_unittests.cc.

559 {
560 Scalar size = 256;
561 Canvas canvas;
562 Paint paint;
563 paint.color = Color::White();
564 canvas.DrawRect(Rect::MakeXYWH(0, 0, size * 3, size * 3), paint);
565 std::vector<Color> colors = {Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF),
566 Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF),
567 Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF),
568 Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF)};
569 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
570 std::array<std::tuple<Point, float, Point, float>, 8> array{
571 std::make_tuple(Point{size / 2.f, size / 2.f}, 0.f,
572 Point{size / 2.f, size / 2.f}, size / 2.f),
573 std::make_tuple(Point{size / 2.f, size / 2.f}, size / 4.f,
574 Point{size / 2.f, size / 2.f}, size / 2.f),
575 std::make_tuple(Point{size / 4.f, size / 4.f}, 0.f,
576 Point{size / 2.f, size / 2.f}, size / 2.f),
577 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 2.f,
578 Point{size / 2.f, size / 2.f}, 0),
579 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 4.f,
580 Point{size / 2.f, size / 2.f}, size / 2.f),
581 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 16.f,
582 Point{size / 2.f, size / 2.f}, size / 8.f),
583 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 8.f,
584 Point{size / 2.f, size / 2.f}, size / 16.f),
585 std::make_tuple(Point{size / 8.f, size / 8.f}, size / 8.f,
586 Point{size / 2.f, size / 2.f}, size / 8.f),
587 };
588 for (int i = 0; i < 8; i++) {
589 canvas.Save();
590 canvas.Translate({(i % 3) * size, i / 3 * size, 0});
591 paint.color_source = ColorSource::MakeConicalGradient(
592 std::get<0>(array[i]), std::get<1>(array[i]), colors, stops,
593 std::get<2>(array[i]), std::get<3>(array[i]), Entity::TileMode::kClamp,
594 {});
595 canvas.DrawRect(Rect::MakeXYWH(0, 0, size, size), paint);
596 canvas.Restore();
597 }
598 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
599 }

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

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

Definition at line 190 of file aiks_gradient_unittests.cc.

190 {
191 CanRenderConicalGradientWithDithering(this, false);
192 }

References CanRenderConicalGradientWithDithering().

## ◆ TEST_P() [34/384]

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

Definition at line 194 of file aiks_gradient_unittests.cc.

194 {
195 CanRenderConicalGradientWithDithering(this, true);
196 }

References CanRenderConicalGradientWithDithering().

## ◆ TEST_P() [35/384]

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

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

Definition at line 2630 of file aiks_unittests.cc.

2630 {
2631 Canvas canvas;
2632
2633 canvas.DrawPaint({.color = Color::Red()});
2634 // Draw an empty savelayer with a destructive blend mode, which will replace
2635 // the entire red screen with fully transparent black, except for the green
2636 // circle drawn within the layer.
2637 canvas.SaveLayer({.blend_mode = BlendMode::kSource});
2638 canvas.DrawCircle({300, 300}, 100, {.color = Color::Green()});
2639 canvas.Restore();
2640
2641 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2642 }

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

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

Definition at line 344 of file aiks_unittests.cc.

344 {
345 Paint paint;
346 Canvas canvas;
347 canvas.Translate({400, 400});
348
349 // Limit drawing to face circle with a clip.
350 canvas.ClipPath(PathBuilder{}.AddCircle(Point(), 200).TakePath());
351 canvas.Save();
352
353 // Cut away eyes/mouth using difference clips.
354 canvas.ClipPath(PathBuilder{}.AddCircle({-100, -50}, 30).TakePath(),
355 Entity::ClipOperation::kDifference);
356 canvas.ClipPath(PathBuilder{}.AddCircle({100, -50}, 30).TakePath(),
357 Entity::ClipOperation::kDifference);
358 canvas.ClipPath(PathBuilder{}
359 .AddQuadraticCurve({-100, 50}, {0, 150}, {100, 50})
360 .TakePath(),
361 Entity::ClipOperation::kDifference);
362
363 // Draw a huge yellow rectangle to prove the clipping works.
364 paint.color = Color::Yellow();
365 canvas.DrawRect(Rect::MakeXYWH(-1000, -1000, 2000, 2000), paint);
366
367 // Remove the difference clips and draw hair that partially covers the eyes.
368 canvas.Restore();
369 paint.color = Color::Maroon();
370 canvas.DrawPath(PathBuilder{}
371 .MoveTo({200, -200})
372 .HorizontalLineTo(-200)
373 .VerticalLineTo(-40)
374 .CubicCurveTo({0, -40}, {0, -80}, {200, -80})
375 .TakePath(),
376 paint);
377
378 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
379 }

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

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(std::move(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() [39/384]

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

Definition at line 440 of file aiks_unittests.cc.

440 {
441 Canvas canvas;
442 Paint paint;
443
444 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
445 Color{0.1294, 0.5882, 0.9529, 1.0}};
446 std::vector<Scalar> stops = {
447 0.0,
448 1.0,
449 };
450
451 paint.color_source = ColorSource::MakeLinearGradient(
452 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
453 Entity::TileMode::kRepeat, {});
454
455 canvas.Save();
456 canvas.Translate({100, 100, 0});
457 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), paint);
458 canvas.Restore();
459
460 canvas.Save();
461 canvas.Translate({100, 400, 0});
462 canvas.DrawCircle({100, 100}, 100, paint);
463 canvas.Restore();
464 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
465 }

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

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

Definition at line 831 of file aiks_unittests.cc.

831 {
832 Canvas canvas;
833 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
834
835 ASSERT_TRUE(RenderTextInCanvasSkia(
836 GetContext(), canvas, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture));
837 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
838 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), kFontFixture, and RenderTextInCanvasSkia().

## ◆ TEST_P() [41/384]

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

Definition at line 853 of file aiks_unittests.cc.

853 {
854 Canvas canvas;
855 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
856
857 ASSERT_TRUE(RenderTextInCanvasSkia(
858 GetContext(), canvas, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
859 {.color = Color::Black().WithAlpha(0.5)}));
860 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
861 }

References impeller::Color::Black(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), kFontFixture, RenderTextInCanvasSkia(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [42/384]

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

Definition at line 840 of file aiks_unittests.cc.

840 {
841 Canvas canvas;
842 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
843
844 ASSERT_TRUE(RenderTextInCanvasSkia(
845 GetContext(), canvas, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
846 TextRenderOptions{.color = Color::Blue(),
847 .mask_blur_descriptor = Paint::MaskBlurDescriptor{
848 .style = FilterContents::BlurStyle::kNormal,
849 .sigma = Sigma(4)}}));
850 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
851 }

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

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

Definition at line 2745 of file aiks_unittests.cc.

2745 {
2746 // This case triggers the ForegroundAdvancedBlend path. The color filter
2747 // should apply to the color only, and respect the alpha mask.
2748 Canvas canvas;
2749 canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
2750 canvas.DrawCircle({400, 400}, 200,
2751 {
2752 .color = Color::Grey(),
2753 .color_filter = ColorFilter::MakeBlend(
2754 BlendMode::kColor, Color::Green()),
2755 .mask_blur_descriptor =
2756 Paint::MaskBlurDescriptor{
2757 .style = FilterContents::BlurStyle::kNormal,
2758 .sigma = Radius(20),
2759 },
2760 });
2761 canvas.Restore();
2762
2763 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2764 }

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

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

Definition at line 2724 of file aiks_unittests.cc.

2724 {
2725 // This case triggers the ForegroundPorterDuffBlend path. The color filter
2726 // should apply to the color only, and respect the alpha mask.
2727 Canvas canvas;
2728 canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
2729 canvas.DrawCircle({400, 400}, 200,
2730 {
2731 .color = Color::White(),
2732 .color_filter = ColorFilter::MakeBlend(
2733 BlendMode::kSource, Color::Green()),
2734 .mask_blur_descriptor =
2735 Paint::MaskBlurDescriptor{
2736 .style = FilterContents::BlurStyle::kNormal,
2737 .sigma = Radius(20),
2738 },
2739 });
2740 canvas.Restore();
2741
2742 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2743 }

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

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

Definition at line 601 of file aiks_gradient_unittests.cc.

601 {
602 std::vector<Color> colors = {Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF),
603 Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF),
604 Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF),
605 Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF)};
606 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
607
608 std::array<ColorSource, 3> color_sources = {
609 ColorSource::MakeLinearGradient({0, 0}, {100, 100}, colors, stops,
610 Entity::TileMode::kDecal, {}),
611 ColorSource::MakeRadialGradient({100, 100}, 100, colors, stops,
612 Entity::TileMode::kDecal, {}),
613 ColorSource::MakeSweepGradient({100, 100}, Degrees(45), Degrees(135),
614 colors, stops, Entity::TileMode::kDecal,
615 {}),
616 };
617
618 Canvas canvas;
619 Paint paint;
620 paint.color = Color::White();
621 canvas.DrawRect(Rect::MakeLTRB(0, 0, 605, 205), paint);
622 for (int i = 0; i < 3; i++) {
623 canvas.Save();
624 canvas.Translate({i * 200.0f, 0, 0});
625 paint.color_source = color_sources[i];
626 canvas.DrawRect(Rect::MakeLTRB(0, 0, 200, 200), paint);
627 canvas.Restore();
628 }
629 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
630 }

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

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

Definition at line 515 of file aiks_unittests.cc.

515 {
516 Canvas canvas;
517
518 Paint red;
519 red.color = Color::Red();
520 Paint green;
521 green.color = Color::Green().WithAlpha(0.5);
522 Paint blue;
523 blue.color = Color::Blue();
524
525 Paint alpha;
526 alpha.color = Color::Red().WithAlpha(0.5);
527
528 canvas.SaveLayer(alpha);
529
530 canvas.DrawRect(Rect::MakeXYWH(000, 000, 100, 100), red);
531 canvas.DrawRect(Rect::MakeXYWH(020, 020, 100, 100), green);
532 canvas.DrawRect(Rect::MakeXYWH(040, 040, 100, 100), blue);
533
534 canvas.Restore();
535
536 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
537 }

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

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

Definition at line 92 of file aiks_unittests.cc.

92 {
93 Canvas canvas;
94 Paint paint;
95 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
96 paint.color = Color::Red();
97 canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
98 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
99 }

References impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::TPoint< Scalar >::MakeXY(), and impeller::Color::Red().

## ◆ TEST_P() [48/384]

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

Definition at line 236 of file aiks_unittests.cc.

236 {
237 Canvas canvas;
238 Paint paint;
239 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
240 Size image_half_size = Size(image->GetSize()) * 0.5;
241
242 // Render the bottom right quarter of the source image in a stretched rect.
243 auto source_rect = Rect::MakeSize(image_half_size);
244 source_rect = source_rect.Shift(Point(image_half_size));
245
246 canvas.DrawImageRect(image, source_rect, Rect::MakeXYWH(100, 100, 600, 600),
247 paint);
248 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
249 }

References impeller::Canvas::DrawImageRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeSize(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [49/384]

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

Definition at line 101 of file aiks_unittests.cc.

101 {
102 Canvas canvas;
103 Paint paint;
104 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
105 paint.color = Color::Red();
106 paint.color_filter =
107 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow());
108 paint.invert_colors = true;
109
110 canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
111 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
112 }

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

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

Definition at line 814 of file aiks_unittests.cc.

814 {
815 Canvas canvas;
816 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
817
818 ASSERT_TRUE(RenderTextInCanvasSkia(
819 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
820 "HomemadeApple.ttf"));
821 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
822 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and RenderTextInCanvasSkia().

## ◆ TEST_P() [51/384]

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

Definition at line 48 of file aiks_gradient_unittests.cc.

48 {
49 CanRenderLinearGradient(this, Entity::TileMode::kClamp);
50 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [52/384]

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

Definition at line 57 of file aiks_gradient_unittests.cc.

57 {
58 CanRenderLinearGradient(this, Entity::TileMode::kDecal);
59 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [53/384]

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

Definition at line 61 of file aiks_gradient_unittests.cc.

61 {
62 Canvas canvas;
63 canvas.Scale(GetContentScale());
64 Paint paint;
65 canvas.Translate({100.0f, 0, 0});
66
67 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
68 Color{0.1294, 0.5882, 0.9529, 0.0}};
69 std::vector<Scalar> stops = {0.0, 1.0};
70
71 paint.color_source = ColorSource::MakeLinearGradient(
72 {0, 0}, {200, 200}, std::move(colors), std::move(stops),
73 Entity::TileMode::kDecal, {});
74 // Overlay the gradient with 25% green. This should appear as the entire
75 // rectangle being drawn with 25% green, including the border area outside the
76 // decal gradient.
77 paint.color_filter = ColorFilter::MakeBlend(BlendMode::kSourceOver,
78 Color::Green().WithAlpha(0.25));
79
80 paint.color = Color(1.0, 1.0, 1.0, 1.0);
81 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
82 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
83 }

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

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

Definition at line 260 of file aiks_gradient_unittests.cc.

260 {
261 CanRenderLinearGradientManyColors(this, Entity::TileMode::kClamp);
262 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [55/384]

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

Definition at line 269 of file aiks_gradient_unittests.cc.

269 {
270 CanRenderLinearGradientManyColors(this, Entity::TileMode::kDecal);
271 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [56/384]

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

Definition at line 266 of file aiks_gradient_unittests.cc.

266 {
267 CanRenderLinearGradientManyColors(this, Entity::TileMode::kMirror);
268 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [57/384]

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

Definition at line 263 of file aiks_gradient_unittests.cc.

263 {
264 CanRenderLinearGradientManyColors(this, Entity::TileMode::kRepeat);
265 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [58/384]

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

Definition at line 303 of file aiks_gradient_unittests.cc.

303 {
304 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
305 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
306 const Entity::TileMode tile_modes[] = {
307 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
308 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
309
310 static int selected_tile_mode = 0;
311 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
312 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
313 sizeof(tile_mode_names) / sizeof(char*));
314 static Matrix matrix = {
315 1, 0, 0, 0, //
316 0, 1, 0, 0, //
317 0, 0, 1, 0, //
318 0, 0, 0, 1 //
319 };
320 std::string label = "##1";
321 for (int i = 0; i < 4; i++) {
322 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float, &(matrix.vec[i]),
323 4, NULL, NULL, "%.2f", 0);
324 label[2]++;
325 }
326 ImGui::End();
327
328 Canvas canvas;
329 Paint paint;
330 canvas.Translate({100.0, 100.0, 0});
331 auto tile_mode = tile_modes[selected_tile_mode];
332
333 std::vector<Color> colors = {
334 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
335 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
336 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
337 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
338 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
339 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
340 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
341 std::vector<Scalar> stops = {
342 0.0, 2.0 / 62.0, 4.0 / 62.0, 8.0 / 62.0, 16.0 / 62.0, 32.0 / 62.0, 1.0,
343 };
344
345 paint.color_source = ColorSource::MakeLinearGradient(
346 {0, 0}, {200, 200}, std::move(colors), std::move(stops), tile_mode, {});
347
348 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
349 return canvas.EndRecordingAsPicture();
350 };
351 ASSERT_TRUE(OpenPlaygroundHere(callback));
352 }

References impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), 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() [59/384]

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

Definition at line 354 of file aiks_gradient_unittests.cc.

354 {
355 Canvas canvas;
356
357 Paint paint = {
358 .color = Color::White(),
359 .color_source = ColorSource::MakeLinearGradient(
360 {200, 200}, {400, 400},
361 {Color::Red(), Color::White(), Color::Red(), Color::White(),
362 Color::Red(), Color::White(), Color::Red(), Color::White(),
363 Color::Red(), Color::White(), Color::Red()},
364 {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0},
365 Entity::TileMode::kClamp, {}),
366 .mask_blur_descriptor =
367 Paint::MaskBlurDescriptor{
368 .style = FilterContents::BlurStyle::kNormal,
369 .sigma = Sigma(20),
370 },
371 };
372
373 canvas.DrawCircle({300, 300}, 200, paint);
374 canvas.DrawRect(Rect::MakeLTRB(100, 300, 500, 600), paint);
375
376 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
377 }

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

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

Definition at line 54 of file aiks_gradient_unittests.cc.

54 {
55 CanRenderLinearGradient(this, Entity::TileMode::kMirror);
56 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [61/384]

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

Definition at line 51 of file aiks_gradient_unittests.cc.

51 {
52 CanRenderLinearGradient(this, Entity::TileMode::kRepeat);
53 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [62/384]

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

Definition at line 299 of file aiks_gradient_unittests.cc.

299 {
300 CanRenderLinearGradientWayManyColors(this, Entity::TileMode::kClamp);
301 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [63/384]

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

Definition at line 105 of file aiks_gradient_unittests.cc.

105 {
106 CanRenderLinearGradientWithDithering(this, false);
107 }

References CanRenderLinearGradientWithDithering().

## ◆ TEST_P() [64/384]

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

Definition at line 109 of file aiks_gradient_unittests.cc.

109 {
110 CanRenderLinearGradientWithDithering(this, true);
111 } // namespace

References CanRenderLinearGradientWithDithering().

## ◆ TEST_P() [65/384]

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

Definition at line 220 of file aiks_gradient_unittests.cc.

220 {
221 CanRenderLinearGradientWithOverlappingStops(this, Entity::TileMode::kClamp);
222 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [66/384]

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

Definition at line 2644 of file aiks_unittests.cc.

2644 {
2645 Canvas canvas;
2646 canvas.DrawCircle({400, 400}, 300,
2647 {.color = Color::Green(),
2648 .mask_blur_descriptor = Paint::MaskBlurDescriptor{
2649 .style = FilterContents::BlurStyle::kNormal,
2650 .sigma = Sigma(99999),
2651 }});
2652 canvas.Restore();
2653
2654 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2655 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kNormal, impeller::Canvas::Restore(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [67/384]

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

Definition at line 331 of file aiks_unittests.cc.

331 {
332 Canvas canvas;
333 Paint paint;
334 paint.color = Color::Fuchsia();
335 canvas.Save();
336 canvas.ClipPath(PathBuilder{}.AddCircle({200, 400}, 300).TakePath());
337 canvas.Restore();
338 canvas.ClipPath(PathBuilder{}.AddCircle({600, 400}, 300).TakePath());
339 canvas.ClipPath(PathBuilder{}.AddCircle({400, 600}, 300).TakePath());
340 canvas.DrawRect(Rect::MakeXYWH(200, 200, 400, 400), paint);
341 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
342 }

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

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 2580 of file aiks_unittests.cc.

2580 {
2581 Canvas canvas;
2582 canvas.debug_options.offscreen_texture_checkerboard = true;
2583
2584 canvas.DrawPaint({.color = Color::AntiqueWhite()});
2585 canvas.DrawCircle({400, 300}, 200,
2586 {.color = Color::CornflowerBlue().WithAlpha(0.75)});
2587
2588 canvas.SaveLayer({.blend_mode = BlendMode::kMultiply});
2589 {
2590 canvas.DrawCircle({500, 400}, 200,
2591 {.color = Color::DarkBlue().WithAlpha(0.75)});
2592 canvas.DrawCircle({550, 450}, 200,
2593 {.color = Color::LightCoral().WithAlpha(0.75),
2594 .blend_mode = BlendMode::kLuminosity});
2595 }
2596 canvas.Restore();
2597
2598 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2599 }

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

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

Definition at line 379 of file aiks_gradient_unittests.cc.

379 {
380 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
381 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
382 const Entity::TileMode tile_modes[] = {
383 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
384 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
385
386 static int selected_tile_mode = 0;
387 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
388 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
389 sizeof(tile_mode_names) / sizeof(char*));
390 static Matrix matrix = {
391 1, 0, 0, 0, //
392 0, 1, 0, 0, //
393 0, 0, 1, 0, //
394 0, 0, 0, 1 //
395 };
396 std::string label = "##1";
397 for (int i = 0; i < 4; i++) {
398 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float, &(matrix.vec[i]),
399 4, NULL, NULL, "%.2f", 0);
400 label[2]++;
401 }
402 ImGui::End();
403
404 Canvas canvas;
405 Paint paint;
406 canvas.Translate({100.0, 100.0, 0});
407 auto tile_mode = tile_modes[selected_tile_mode];
408
409 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
410 Color{0.1294, 0.5882, 0.9529, 1.0}};
411 std::vector<Scalar> stops = {0.0, 1.0};
412
413 paint.color_source = ColorSource::MakeRadialGradient(
414 {100, 100}, 100, std::move(colors), std::move(stops), tile_mode, {});
415
416 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
417 return canvas.EndRecordingAsPicture();
418 };
419 ASSERT_TRUE(OpenPlaygroundHere(callback));
420 }

References impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), 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() [70/384]

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

Definition at line 422 of file aiks_gradient_unittests.cc.

422 {
423 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
424 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
425 const Entity::TileMode tile_modes[] = {
426 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
427 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
428
429 static int selected_tile_mode = 0;
430 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
431 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
432 sizeof(tile_mode_names) / sizeof(char*));
433 static Matrix matrix = {
434 1, 0, 0, 0, //
435 0, 1, 0, 0, //
436 0, 0, 1, 0, //
437 0, 0, 0, 1 //
438 };
439 std::string label = "##1";
440 for (int i = 0; i < 4; i++) {
441 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float, &(matrix.vec[i]),
442 4, NULL, NULL, "%.2f", 0);
443 label[2]++;
444 }
445 ImGui::End();
446
447 Canvas canvas;
448 Paint paint;
449 canvas.Translate({100.0, 100.0, 0});
450 auto tile_mode = tile_modes[selected_tile_mode];
451
452 std::vector<Color> colors = {
453 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
454 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
455 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
456 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
457 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
458 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
459 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
460 std::vector<Scalar> stops = {
461 0.0,
462 (1.0 / 6.0) * 1,
463 (1.0 / 6.0) * 2,
464 (1.0 / 6.0) * 3,
465 (1.0 / 6.0) * 4,
466 (1.0 / 6.0) * 5,
467 1.0,
468 };
469
470 paint.color_source = ColorSource::MakeRadialGradient(
471 {100, 100}, 100, std::move(colors), std::move(stops), tile_mode, {});
472
473 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
474 return canvas.EndRecordingAsPicture();
475 };
476 ASSERT_TRUE(OpenPlaygroundHere(callback));
477 }

References impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), 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() [71/384]

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

Definition at line 132 of file aiks_gradient_unittests.cc.

132 {
133 CanRenderRadialGradientWithDithering(this, false);
134 }

References CanRenderRadialGradientWithDithering().

## ◆ TEST_P() [72/384]

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

Definition at line 136 of file aiks_gradient_unittests.cc.

136 {
137 CanRenderRadialGradientWithDithering(this, true);
138 }

References CanRenderRadialGradientWithDithering().

## ◆ TEST_P() [73/384]

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

Definition at line 656 of file aiks_unittests.cc.

656 {
657 Canvas canvas;
658
659 Paint paint;
660 paint.color = Color::Red();
661
662 PathBuilder::RoundingRadii radii;
663 radii.top_left = {50, 25};
664 radii.top_right = {25, 50};
665 radii.bottom_right = {50, 25};
666 radii.bottom_left = {25, 50};
667
668 auto path = PathBuilder{}
669 .AddRoundedRect(Rect::MakeXYWH(100, 100, 500, 500), radii)
670 .TakePath();
671
672 canvas.DrawPath(std::move(path), paint);
673
674 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
675 }

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

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

Definition at line 251 of file aiks_unittests.cc.

251 {
252 Canvas canvas;
253 canvas.Scale(GetContentScale());
254 Paint paint;
255
256 paint.color = Color::White();
257 canvas.DrawPaint(paint);
258
259 auto draw = [&canvas](const Paint& paint, Scalar x, Scalar y) {
260 canvas.Save();
261 canvas.Translate({x, y});
262 {
263 canvas.Save();
264 canvas.ClipRect(Rect::MakeLTRB(50, 50, 150, 150));
265 canvas.DrawPaint(paint);
266 canvas.Restore();
267 }
268 {
269 canvas.Save();
270 canvas.ClipOval(Rect::MakeLTRB(200, 50, 300, 150));
271 canvas.DrawPaint(paint);
272 canvas.Restore();
273 }
274 {
275 canvas.Save();
276 canvas.ClipRRect(Rect::MakeLTRB(50, 200, 150, 300), {20, 20});
277 canvas.DrawPaint(paint);
278 canvas.Restore();
279 }
280 {
281 canvas.Save();
282 canvas.ClipRRect(Rect::MakeLTRB(200, 230, 300, 270), {20, 20});
283 canvas.DrawPaint(paint);
284 canvas.Restore();
285 }
286 {
287 canvas.Save();
288 canvas.ClipRRect(Rect::MakeLTRB(230, 200, 270, 300), {20, 20});
289 canvas.DrawPaint(paint);
290 canvas.Restore();
291 }
292 canvas.Restore();
293 };
294
295 paint.color = Color::Blue();
296 draw(paint, 0, 0);
297
298 std::vector<Color> gradient_colors = {
299 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
300 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
301 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
302 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
303 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
304 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
305 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
306 std::vector<Scalar> stops = {
307 0.0,
308 (1.0 / 6.0) * 1,
309 (1.0 / 6.0) * 2,
310 (1.0 / 6.0) * 3,
311 (1.0 / 6.0) * 4,
312 (1.0 / 6.0) * 5,
313 1.0,
314 };
315 auto texture = CreateTextureForFixture("airplane.jpg",
316 /*enable_mipmapping=*/true);
317
318 paint.color_source = ColorSource::MakeRadialGradient(
319 {500, 600}, 75, std::move(gradient_colors), std::move(stops),
320 Entity::TileMode::kMirror, {});
321 draw(paint, 0, 300);
322
323 paint.color_source = ColorSource::MakeImage(
324 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
325 Matrix::MakeTranslation({0, 0}));
326 draw(paint, 300, 0);
327
328 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
329 }

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

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

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

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

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

Definition at line 499 of file aiks_gradient_unittests.cc.

499 {
500 CanRenderSweepGradient(this, Entity::TileMode::kClamp);
501 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [79/384]

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

Definition at line 508 of file aiks_gradient_unittests.cc.

508 {
509 CanRenderSweepGradient(this, Entity::TileMode::kDecal);
510 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [80/384]

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

Definition at line 546 of file aiks_gradient_unittests.cc.

546 {
547 CanRenderSweepGradientManyColors(this, Entity::TileMode::kClamp);
548 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [81/384]

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

Definition at line 555 of file aiks_gradient_unittests.cc.

555 {
556 CanRenderSweepGradientManyColors(this, Entity::TileMode::kDecal);
557 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [82/384]

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

Definition at line 552 of file aiks_gradient_unittests.cc.

552 {
553 CanRenderSweepGradientManyColors(this, Entity::TileMode::kMirror);
554 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [83/384]

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

Definition at line 549 of file aiks_gradient_unittests.cc.

549 {
550 CanRenderSweepGradientManyColors(this, Entity::TileMode::kRepeat);
551 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [84/384]

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

Definition at line 505 of file aiks_gradient_unittests.cc.

505 {
506 CanRenderSweepGradient(this, Entity::TileMode::kMirror);
507 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [85/384]

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

Definition at line 502 of file aiks_gradient_unittests.cc.

502 {
503 CanRenderSweepGradient(this, Entity::TileMode::kRepeat);
504 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [86/384]

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

Definition at line 161 of file aiks_gradient_unittests.cc.

161 {
162 CanRenderSweepGradientWithDithering(this, false);
163 }

References CanRenderSweepGradientWithDithering().

## ◆ TEST_P() [87/384]

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

Definition at line 165 of file aiks_gradient_unittests.cc.

165 {
166 CanRenderSweepGradientWithDithering(this, true);
167 }

References CanRenderSweepGradientWithDithering().

## ◆ TEST_P() [88/384]

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

Definition at line 751 of file aiks_unittests.cc.

751 {
752 Canvas canvas;
753 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
754 ASSERT_TRUE(RenderTextInCanvasSkia(
755 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
756 "Roboto-Regular.ttf"));
757 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
758 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and RenderTextInCanvasSkia().

## ◆ TEST_P() [89/384]

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

Definition at line 760 of file aiks_unittests.cc.

760 {
761 Canvas canvas;
762 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
763 ASSERT_TRUE(RenderTextInCanvasSTB(
764 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
765 "Roboto-Regular.ttf"));
766
767 SetTypographerContext(TypographerContextSTB::Make());
768 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
769 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::TypographerContextSTB::Make(), and RenderTextInCanvasSTB().

## ◆ TEST_P() [90/384]

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

Definition at line 863 of file aiks_unittests.cc.

863 {
864 Canvas canvas;
865 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
866
867 canvas.Translate({100, 100});
868 canvas.Scale(Vector2{0.5, 0.5});
869
870 // Blend the layer with the parent pass using kClear to expose the coverage.
871 canvas.SaveLayer({.blend_mode = BlendMode::kClear});
872 ASSERT_TRUE(RenderTextInCanvasSkia(
873 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
874 "Roboto-Regular.ttf"));
875 canvas.Restore();
876
877 // Render the text again over the cleared coverage rect.
878 ASSERT_TRUE(RenderTextInCanvasSkia(
879 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
880 "Roboto-Regular.ttf"));
881
882 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
883 }

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

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

Definition at line 885 of file aiks_unittests.cc.

885 {
886 Canvas canvas;
887 canvas.Translate({200, 150});
888
889 // Construct the text blob.
890 auto mapping = flutter::testing::OpenFixtureAsSkData("wtf.otf");
891 ASSERT_NE(mapping, nullptr);
892
893 Scalar font_size = 80;
894 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
895 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
896
897 Paint text_paint;
898 text_paint.color = Color::Blue().WithAlpha(0.8);
899
900 struct {
901 Point position;
902 const char* text;
903 } text[] = {{Point(0, 0), "0F0F0F0"},
904 {Point(1, 2), "789"},
905 {Point(1, 3), "456"},
906 {Point(1, 4), "123"},
907 {Point(0, 6), "0F0F0F0"}};
908 for (auto& t : text) {
909 canvas.Save();
910 canvas.Translate(t.position * Point(font_size * 2, font_size * 1.1));
911 {
912 auto blob = SkTextBlob::MakeFromString(t.text, sk_font);
913 ASSERT_NE(blob, nullptr);
914 auto frame = MakeTextFrameFromTextBlobSkia(blob);
915 canvas.DrawTextFrame(frame, Point(), text_paint);
916 }
917 canvas.Restore();
918 }
919
920 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
921 }

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

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

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

Definition at line 211 of file aiks_unittests.cc.

211 {
212 CanRenderTiledTexture(this, Entity::TileMode::kClamp);
213 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [94/384]

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

Definition at line 215 of file aiks_unittests.cc.

215 {
216 CanRenderTiledTexture(this, Entity::TileMode::kClamp, /*async_submit=*/true);
217 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [95/384]

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

Definition at line 231 of file aiks_unittests.cc.

231 {
232 CanRenderTiledTexture(this, Entity::TileMode::kClamp, /*async_submit=*/false,
233 Matrix::MakeTranslation({172.f, 172.f, 0.f}));
234 }

References impeller::Entity::kClamp, and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [96/384]

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

Definition at line 227 of file aiks_unittests.cc.

227 {
228 CanRenderTiledTexture(this, Entity::TileMode::kDecal);
229 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [97/384]

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

Definition at line 223 of file aiks_unittests.cc.

223 {
224 CanRenderTiledTexture(this, Entity::TileMode::kMirror);
225 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [98/384]

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

Definition at line 219 of file aiks_unittests.cc.

219 {
220 CanRenderTiledTexture(this, Entity::TileMode::kRepeat);
221 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [99/384]

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 2560 of file aiks_unittests.cc.

2560 {
2561 Canvas canvas;
2562 canvas.DrawPaint({.color = Color::Red()});
2563
2564 // Draw two overlapping subpixel circles.
2565 canvas.SaveLayer({});
2566 canvas.DrawCircle({100, 100}, 0.1, {.color = Color::Yellow()});
2567 canvas.Restore();
2568 canvas.SaveLayer({});
2569 canvas.DrawCircle({100, 100}, 0.1, {.color = Color::Yellow()});
2570 canvas.Restore();
2571
2572 canvas.DrawPaint({.color = Color::Green()});
2573
2574 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2575 }

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

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

Definition at line 381 of file aiks_unittests.cc.

381 {
382 Canvas canvas;
383
384 // Cover the whole canvas with red.
385 canvas.DrawPaint({.color = Color::Red()});
386
387 canvas.Save();
388
389 // Append two clips, the second resulting in empty coverage.
390 canvas.ClipPath(
391 PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath());
392 canvas.ClipPath(
393 PathBuilder{}.AddRect(Rect::MakeXYWH(300, 300, 100, 100)).TakePath());
394
395 // Restore to no clips.
396 canvas.Restore();
397
398 // Replace the whole canvas with green.
399 canvas.DrawPaint({.color = Color::Green()});
400
401 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
402 }

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

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

Definition at line 422 of file aiks_unittests.cc.

422 {
423 Canvas canvas;
424
425 Paint red;
426 red.color = Color::Red();
427
428 Paint alpha;
429 alpha.color = Color::Red().WithAlpha(0.5);
430
431 canvas.SaveLayer(alpha);
432
433 canvas.DrawCircle({125, 125}, 125, red);
434
435 canvas.Restore();
436
437 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
438 }

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

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

Definition at line 65 of file aiks_unittests.cc.

65 {
66 Canvas canvas;
67 ASSERT_EQ(canvas.GetSaveCount(), 1u);
68 ASSERT_EQ(canvas.Restore(), false);
69
70 canvas.Translate(Size{100, 100});
71 canvas.Save();
72 ASSERT_EQ(canvas.GetSaveCount(), 2u);
73 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(),
74 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
75 ASSERT_TRUE(canvas.Restore());
76 ASSERT_EQ(canvas.GetSaveCount(), 1u);
77 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(),
78 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
79 }

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

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

Definition at line 56 of file aiks_unittests.cc.

56 {
57 Canvas canvas;
58 Matrix identity;
59 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(), identity);
60 canvas.Translate(Size{100, 100});
61 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(),
62 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
63 }

References ASSERT_MATRIX_NEAR, impeller::Canvas::GetCurrentTransform(), impeller::Matrix::MakeTranslation(), and impeller::Canvas::Translate().

## ◆ TEST_P() [104/384]

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

Definition at line 3249 of file aiks_unittests.cc.

3249 {
3250 auto capture_context = CaptureContext::MakeAllowlist({"TestDocument"});
3251
3252 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
3253 Canvas canvas;
3254
3255 capture_context.Rewind();
3256 auto document = capture_context.GetDocument("TestDocument");
3257
3258 auto color = document.AddColor("Background color", Color::CornflowerBlue());
3259 canvas.DrawPaint({.color = color});
3260
3261 ImGui::Begin("TestDocument", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
3262 document.GetElement()->properties.Iterate([](CaptureProperty& property) {
3263 property.Invoke({.color = [](CaptureColorProperty& p) {
3264 ImGui::ColorEdit4(p.label.c_str(), reinterpret_cast<float*>(&p.value));
3265 }});
3266 });
3267 ImGui::End();
3268
3269 return canvas.EndRecordingAsPicture();
3270 };
3271 OpenPlaygroundHere(callback);
3272 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and impeller::CaptureContext::MakeAllowlist().

## ◆ TEST_P() [105/384]

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

Definition at line 3274 of file aiks_unittests.cc.

3274 {
3275 ASSERT_FALSE(GetContext()->capture.IsActive());
3276 }

## ◆ TEST_P() [106/384]

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

Definition at line 3374 of file aiks_unittests.cc.

3374 {
3375 Canvas canvas;
3376 Paint white;
3377 white.color = Color::Blue();
3378 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600.0, 600.0), white);
3379
3380 Paint clear;
3381 clear.blend_mode = BlendMode::kClear;
3382
3383 canvas.DrawCircle(Point::MakeXY(300.0, 300.0), 200.0, clear);
3384 }

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

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

Definition at line 3356 of file aiks_unittests.cc.

3356 {
3357 Canvas canvas;
3358 Paint white;
3359 white.color = Color::Blue();
3360 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600.0, 600.0), white);
3361
3362 Paint clear;
3363 clear.blend_mode = BlendMode::kClear;
3364 clear.mask_blur_descriptor = Paint::MaskBlurDescriptor{
3365 .style = FilterContents::BlurStyle::kNormal,
3366 .sigma = Sigma(20),
3367 };
3368
3369 canvas.DrawCircle(Point::MakeXY(300.0, 300.0), 200.0, clear);
3370
3371 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3372 }

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

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

Definition at line 2078 of file aiks_unittests.cc.

2078 {
2079 Canvas canvas;
2080 canvas.SaveLayer({}, std::nullopt,
2081 ImageFilter::MakeBlur(Sigma(3), Sigma(3),
2082 FilterContents::BlurStyle::kNormal,
2083 Entity::TileMode::kClamp));
2084 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
2085 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
2086 .blend_mode = BlendMode::kSourceOver});
2087 canvas.Restore();
2088
2089 Picture picture = canvas.EndRecordingAsPicture();
2090
2091 std::optional<Color> actual_color;
2092 bool found_subpass = false;
2093 picture.pass->IterateAllElements([&](EntityPass::Element& element) -> bool {
2094 if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
2095 actual_color = subpass->get()->GetClearColor();
2096 found_subpass = true;
2097 }
2098 // Fail if the first element isn't a subpass.
2099 return true;
2100 });
2101
2102 EXPECT_TRUE(found_subpass);
2103 EXPECT_FALSE(actual_color.has_value());
2104 }

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

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

Definition at line 3439 of file aiks_unittests.cc.

3439 {
3440 SetWindowSize({400, 400});
3441 Canvas canvas;
3442 canvas.Scale(GetContentScale());
3443 canvas.DrawRect(Rect::MakeLTRB(200, 200, 300, 300), {.color = Color::Red()});
3444 canvas.SaveLayer({
3445 .image_filter = std::make_shared<MatrixImageFilter>(
3446 Matrix::MakeScale({2, 2, 1}), SamplerDescriptor{}),
3447 });
3448 // Draw a rectangle that would fully cover the parent pass size, but not
3449 // the subpass that it is rendered in.
3450 canvas.DrawRect(Rect::MakeLTRB(0, 0, 400, 400), {.color = Color::Green()});
3451 // Draw a bigger rectangle to force the subpass to be bigger.
3452 canvas.DrawRect(Rect::MakeLTRB(0, 0, 800, 800), {.color = Color::Red()});
3453 canvas.Restore();
3454
3455 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3456 }

References impeller::Color::Green(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Color::Red(), and impeller::Canvas::Scale().

## ◆ TEST_P() [110/384]

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

Definition at line 3234 of file aiks_unittests.cc.

3234 {
3235 Canvas canvas;
3236 canvas.Translate(Point(0, -400));
3237 Paint paint;
3238 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
3239 .style = FilterContents::BlurStyle::kNormal,
3240 .sigma = Radius{120 * 3},
3241 };
3242 paint.color = Color::Red();
3243 PathBuilder builder{};
3244 builder.AddRect(Rect::MakeLTRB(0, 0, 800, 800));
3245 canvas.DrawPath(builder.TakePath(), paint);
3246 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3247 }

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

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

Definition at line 3214 of file aiks_unittests.cc.

3214 {
3215 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
3216 auto point = IMPELLER_PLAYGROUND_POINT(Point(400, 400), 20, Color::Green());
3217
3218 Canvas canvas;
3219 canvas.Translate(point - Point(400, 400));
3220 Paint paint;
3221 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
3222 .style = FilterContents::BlurStyle::kNormal,
3223 .sigma = Radius{120 * 3},
3224 };
3225 paint.color = Color::Red();
3226 PathBuilder builder{};
3227 builder.AddRect(Rect::MakeLTRB(0, 0, 800, 800));
3228 canvas.DrawPath(builder.TakePath(), paint);
3229 return canvas.EndRecordingAsPicture();
3230 };
3231 ASSERT_TRUE(OpenPlaygroundHere(callback));
3232 }

References impeller::PathBuilder::AddRect(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), IMPELLER_PLAYGROUND_POINT, 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/384]

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

Definition at line 2054 of file aiks_unittests.cc.

2054 {
2055 Canvas canvas(Rect::MakeXYWH(0, 0, 100, 100));
2056 canvas.ClipRect(Rect::MakeXYWH(0, 0, 100, 100));
2057 canvas.ClipRect(Rect::MakeXYWH(-100, -100, 300, 300));
2058 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
2059 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
2060 .blend_mode = BlendMode::kSourceOver});
2061
2062 Picture picture = canvas.EndRecordingAsPicture();
2063 auto expected = Color::Red().Blend(Color::CornflowerBlue().WithAlpha(0.75),
2064 BlendMode::kSourceOver);
2065 ASSERT_EQ(picture.pass->GetClearColor(), expected);
2066
2067 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2068 std::shared_ptr<Context> real_context = GetContext();
2069 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2070 AiksContext renderer(mock_context, nullptr);
2071 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
2072
2073 ASSERT_EQ(spy->render_passes_.size(), 1llu);
2074 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2075 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
2076 }

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

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

Definition at line 404 of file aiks_unittests.cc.

404 {
405 std::array<Color, 5> colors = {Color::White(), Color::Black(),
406 Color::SkyBlue(), Color::Red(),
407 Color::Yellow()};
408 Canvas canvas;
409 Paint paint;
410
411 canvas.Translate(Vector3(300, 300));
412 for (int i = 0; i < 15; i++) {
413 canvas.Scale(Vector3(0.8, 0.8));
414
415 paint.color = colors[i % colors.size()];
416 canvas.ClipPath(PathBuilder{}.AddCircle({0, 0}, 300).TakePath());
417 canvas.DrawRect(Rect::MakeXYWH(-300, -300, 600, 600), paint);
418 }
419 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
420 }

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

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

Definition at line 2106 of file aiks_unittests.cc.

2106 {
2107 Canvas canvas;
2108 canvas.DrawPaint(
2109 {.color = Color::Yellow(), .blend_mode = BlendMode::kSource});
2110 canvas.SaveLayer({.blend_mode = BlendMode::kMultiply});
2111 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
2112 .blend_mode = BlendMode::kSourceOver});
2113
2114 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2115 }

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

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

Definition at line 2117 of file aiks_unittests.cc.

2117 {
2118 // Bug: https://github.com/flutter/flutter/issues/131576
2119 Canvas canvas;
2120 canvas.DrawPaint(
2121 {.color = Color::Yellow(), .blend_mode = BlendMode::kSource});
2122 canvas.SaveLayer({}, {},
2123 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
2124 FilterContents::BlurStyle::kNormal,
2125 Entity::TileMode::kDecal));
2126 canvas.DrawPaint(
2127 {.color = Color::CornflowerBlue(), .blend_mode = BlendMode::kSourceOver});
2128
2129 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2130 }

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

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

Definition at line 2147 of file aiks_unittests.cc.

2147 {
2148 Canvas canvas;
2149
2150 canvas.SaveLayer({
2151 .color_filter =
2152 ColorFilter::MakeMatrix({.array =
2153 {
2154 -1.0, 0, 0, 1.0, 0, //
2155 0, -1.0, 0, 1.0, 0, //
2156 0, 0, -1.0, 1.0, 0, //
2157 1.0, 1.0, 1.0, 1.0, 0 //
2158 }}),
2159 });
2160
2161 canvas.Translate({500, 300, 0});
2162 canvas.Rotate(Radians(2 * kPi / 3));
2163 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
2164
2165 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2166 }

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

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 1072 of file aiks_unittests.cc.

1072 {
1073 // Compare with https://fiddle.skia.org/c/@BlendModes
1074
1075 BlendModeSelection blend_modes = GetBlendModeSelection();
1076
1077 auto draw_color_wheel = [](Canvas& canvas) {
1078 /// color_wheel_sampler: r=0 -> fuchsia, r=2pi/3 -> yellow, r=4pi/3 ->
1079 /// cyan domain: r >= 0 (because modulo used is non euclidean)
1080 auto color_wheel_sampler = [](Radians r) {
1081 Scalar x = r.radians / k2Pi + 1;
1082
1083 // https://www.desmos.com/calculator/6nhjelyoaj
1084 auto color_cycle = [](Scalar x) {
1085 Scalar cycle = std::fmod(x, 6.0f);
1086 return std::max(0.0f, std::min(1.0f, 2 - std::abs(2 - cycle)));
1087 };
1088 return Color(color_cycle(6 * x + 1), //
1089 color_cycle(6 * x - 1), //
1090 color_cycle(6 * x - 3), //
1091 1);
1092 };
1093
1094 Paint paint;
1095 paint.blend_mode = BlendMode::kSourceOver;
1096
1097 // Draw a fancy color wheel for the backdrop.
1098 // https://www.desmos.com/calculator/xw7kafthwd
1099 const int max_dist = 900;
1100 for (int i = 0; i <= 900; i++) {
1101 Radians r(kPhi / k2Pi * i);
1102 Scalar distance = r.radians / std::powf(4.12, 0.0026 * r.radians);
1103 Scalar normalized_distance = static_cast<Scalar>(i) / max_dist;
1104
1105 paint.color =
1106 color_wheel_sampler(r).WithAlpha(1.0f - normalized_distance);
1107 Point position(distance * std::sin(r.radians),
1108 -distance * std::cos(r.radians));
1109
1110 canvas.DrawCircle(position, 9 + normalized_distance * 3, paint);
1111 }
1112 };
1113
1114 std::shared_ptr<Image> color_wheel_image;
1115 Matrix color_wheel_transform;
1116
1117 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1118 // UI state.
1119 static bool cache_the_wheel = true;
1120 static int current_blend_index = 3;
1121 static float dst_alpha = 1;
1122 static float src_alpha = 1;
1123 static Color color0 = Color::Red();
1124 static Color color1 = Color::Green();
1125 static Color color2 = Color::Blue();
1126
1127 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1128 {
1129 ImGui::Checkbox("Cache the wheel", &cache_the_wheel);
1130 ImGui::ListBox("Blending mode", &current_blend_index,
1131 blend_modes.blend_mode_names.data(),
1132 blend_modes.blend_mode_names.size());
1133 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
1134 ImGui::ColorEdit4("Color A", reinterpret_cast<float*>(&color0));
1135 ImGui::ColorEdit4("Color B", reinterpret_cast<float*>(&color1));
1136 ImGui::ColorEdit4("Color C", reinterpret_cast<float*>(&color2));
1137 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
1138 }
1139 ImGui::End();
1140
1141 static Point content_scale;
1142 Point new_content_scale = GetContentScale();
1143
1144 if (!cache_the_wheel || new_content_scale != content_scale) {
1145 content_scale = new_content_scale;
1146
1147 // Render the color wheel to an image.
1148
1149 Canvas canvas;
1150 canvas.Scale(content_scale);
1151
1152 canvas.Translate(Vector2(500, 400));
1153 canvas.Scale(Vector2(3, 3));
1154
1155 draw_color_wheel(canvas);
1156 auto color_wheel_picture = canvas.EndRecordingAsPicture();
1157 auto snapshot = color_wheel_picture.Snapshot(renderer);
1158 if (!snapshot.has_value() || !snapshot->texture) {
1159 return std::nullopt;
1160 }
1161 color_wheel_image = std::make_shared<Image>(snapshot->texture);
1162 color_wheel_transform = snapshot->transform;
1163 }
1164
1165 Canvas canvas;
1166
1167 // Blit the color wheel backdrop to the screen with managed alpha.
1168 canvas.SaveLayer({.color = Color::White().WithAlpha(dst_alpha),
1169 .blend_mode = BlendMode::kSource});
1170 {
1171 canvas.DrawPaint({.color = Color::White()});
1172
1173 canvas.Save();
1174 canvas.Transform(color_wheel_transform);
1175 canvas.DrawImage(color_wheel_image, Point(), Paint());
1176 canvas.Restore();
1177 }
1178 canvas.Restore();
1179
1180 canvas.Scale(content_scale);
1181 canvas.Translate(Vector2(500, 400));
1182 canvas.Scale(Vector2(3, 3));
1183
1184 // Draw 3 circles to a subpass and blend it in.
1185 canvas.SaveLayer(
1186 {.color = Color::White().WithAlpha(src_alpha),
1187 .blend_mode = blend_modes.blend_mode_values[current_blend_index]});
1188 {
1189 Paint paint;
1190 paint.blend_mode = BlendMode::kPlus;
1191 const Scalar x = std::sin(k2Pi / 3);
1192 const Scalar y = -std::cos(k2Pi / 3);
1193 paint.color = color0;
1194 canvas.DrawCircle(Point(-x, y) * 45, 65, paint);
1195 paint.color = color1;
1196 canvas.DrawCircle(Point(0, -1) * 45, 65, paint);
1197 paint.color = color2;
1198 canvas.DrawCircle(Point(x, y) * 45, 65, paint);
1199 }
1200 canvas.Restore();
1201
1202 return canvas.EndRecordingAsPicture();
1203 };
1204
1205 ASSERT_TRUE(OpenPlaygroundHere(callback));
1206 }

References impeller::Paint::blend_mode, impeller::testing::BlendModeSelection::blend_mode_names, impeller::testing::BlendModeSelection::blend_mode_values, impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawImage(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), GetBlendModeSelection(), impeller::Color::Green(), 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() [118/384]

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

Definition at line 539 of file aiks_unittests.cc.

539 {
540 Canvas canvas;
541
542 // Render a texture directly.
543 {
544 Paint paint;
545 auto image =
546 std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
547 paint.color = Color::Red();
548
549 canvas.Save();
550 canvas.Translate({100, 200, 0});
551 canvas.Scale(Vector2{0.5, 0.5});
552 canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
553 canvas.Restore();
554 }
555
556 // Render an offscreen rendered texture.
557 {
558 Paint red;
559 red.color = Color::Red();
560 Paint green;
561 green.color = Color::Green();
562 Paint blue;
563 blue.color = Color::Blue();
564
565 Paint alpha;
566 alpha.color = Color::Red().WithAlpha(0.5);
567
568 canvas.SaveLayer(alpha);
569
570 canvas.DrawRect(Rect::MakeXYWH(000, 000, 100, 100), red);
571 canvas.DrawRect(Rect::MakeXYWH(020, 020, 100, 100), green);
572 canvas.DrawRect(Rect::MakeXYWH(040, 040, 100, 100), blue);
573
574 canvas.Restore();
575 }
576
577 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
578 }

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

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

Definition at line 1675 of file aiks_unittests.cc.

1675 {
1676 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1677 Canvas canvas;
1678 canvas.Scale(GetContentScale());
1679
1680 Paint alpha;
1681 alpha.color = Color::Red().WithAlpha(0.5);
1682
1683 auto current = Point{25, 25};
1684 const auto offset = Point{25, 25};
1685 const auto size = Size(100, 100);
1686
1687 auto [b0, b1] = IMPELLER_PLAYGROUND_LINE(Point(40, 40), Point(160, 160), 10,
1688 Color::White(), Color::White());
1689 auto bounds = Rect::MakeLTRB(b0.x, b0.y, b1.x, b1.y);
1690
1691 canvas.DrawRect(bounds, Paint{.color = Color::Yellow(),
1692 .stroke_width = 5.0f,
1693 .style = Paint::Style::kStroke});
1694
1695 canvas.SaveLayer(alpha, bounds);
1696
1697 canvas.DrawRect(Rect::MakeOriginSize(current, size),
1698 Paint{.color = Color::Red()});
1699 canvas.DrawRect(Rect::MakeOriginSize(current += offset, size),
1700 Paint{.color = Color::Green()});
1701 canvas.DrawRect(Rect::MakeOriginSize(current += offset, size),
1702 Paint{.color = Color::Blue()});
1703
1704 canvas.Restore();
1705
1706 return canvas.EndRecordingAsPicture();
1707 };
1708
1709 ASSERT_TRUE(OpenPlaygroundHere(callback));
1710 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), IMPELLER_PLAYGROUND_LINE, impeller::Paint::kStroke, impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeOriginSize(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), impeller::Color::White(), impeller::Color::WithAlpha(), and impeller::Color::Yellow().

## ◆ TEST_P() [120/384]

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

Definition at line 980 of file aiks_unittests.cc.

980 {
981 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
982 Color{0.1294, 0.5882, 0.9529, 1.0}};
983 std::vector<Scalar> stops = {0.0, 1.0};
984
985 Paint paint = {
986 .color_source = ColorSource::MakeLinearGradient(
987 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
988 Entity::TileMode::kRepeat, Matrix::MakeScale(Vector3(0.3, 0.3, 0.3))),
989 .blend_mode = BlendMode::kLighten,
990 };
991
992 Canvas canvas;
993 canvas.DrawPaint({.color = Color::Blue()});
994 canvas.Scale(Vector2(2, 2));
995 canvas.ClipRect(Rect::MakeLTRB(0, 0, 200, 200));
996 canvas.DrawCircle({100, 100}, 100, paint);
997 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
998 }

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

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

Definition at line 2900 of file aiks_unittests.cc.

2900 {
2901 // Draws the image as four squares stiched together.
2902 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
2903 auto size = atlas->GetSize();
2904 auto image = std::make_shared<Image>(atlas);
2905 // Divide image into four quadrants.
2906 Scalar half_width = size.width / 2;
2907 Scalar half_height = size.height / 2;
2908 std::vector<Rect> texture_coordinates = {
2909 Rect::MakeLTRB(0, 0, half_width, half_height),
2910 Rect::MakeLTRB(half_width, 0, size.width, half_height),
2911 Rect::MakeLTRB(0, half_height, half_width, size.height),
2912 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
2913 // Position quadrants adjacent to eachother.
2914 std::vector<Matrix> transforms = {
2915 Matrix::MakeTranslation({0, 0, 0}),
2916 Matrix::MakeTranslation({half_width, 0, 0}),
2917 Matrix::MakeTranslation({0, half_height, 0}),
2918 Matrix::MakeTranslation({half_width, half_height, 0})};
2919
2920 Paint paint;
2921
2922 Canvas canvas;
2923 canvas.Scale({0.25, 0.25, 1.0});
2924 canvas.DrawAtlas(image, transforms, texture_coordinates, {},
2925 BlendMode::kModulate, {}, std::nullopt, paint);
2926
2927 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2928 }

References impeller::Canvas::DrawAtlas(), impeller::Canvas::EndRecordingAsPicture(), impeller::kModulate, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), and impeller::Canvas::Scale().

## ◆ TEST_P() [122/384]

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

Definition at line 2867 of file aiks_unittests.cc.

2867 {
2868 // Draws the image as four squares stiched together.
2869 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
2870 auto size = atlas->GetSize();
2871 auto image = std::make_shared<Image>(atlas);
2872 // Divide image into four quadrants.
2873 Scalar half_width = size.width / 2;
2874 Scalar half_height = size.height / 2;
2875 std::vector<Rect> texture_coordinates = {
2876 Rect::MakeLTRB(0, 0, half_width, half_height),
2877 Rect::MakeLTRB(half_width, 0, size.width, half_height),
2878 Rect::MakeLTRB(0, half_height, half_width, size.height),
2879 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
2880 // Position quadrants adjacent to eachother.
2881 std::vector<Matrix> transforms = {
2882 Matrix::MakeTranslation({0, 0, 0}),
2883 Matrix::MakeTranslation({half_width, 0, 0}),
2884 Matrix::MakeTranslation({0, half_height, 0}),
2885 Matrix::MakeTranslation({half_width, half_height, 0})};
2886 std::vector<Color> colors = {Color::Red(), Color::Green(), Color::Blue(),
2887 Color::Yellow()};
2888
2889 Paint paint;
2890
2891 Canvas canvas;
2892 canvas.Scale({0.25, 0.25, 1.0});
2893 canvas.DrawAtlas(image, transforms, texture_coordinates, colors,
2894 BlendMode::kModulate, {}, std::nullopt, paint);
2895
2896 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2897 }

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

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

Definition at line 244 of file aiks_path_unittests.cc.

244 {
245 Canvas canvas;
246 canvas.Scale(GetContentScale());
247 Paint paint;
248 paint.color = Color::Blue();
249 paint.stroke_width = 10;
250
251 auto draw = [&canvas](Paint& paint) {
252 for (auto cap : {Cap::kButt, Cap::kSquare, Cap::kRound}) {
253 paint.stroke_cap = cap;
254 Point origin = {100, 100};
255 Point p0 = {50, 0};
256 Point p1 = {150, 0};
257 canvas.DrawLine({150, 100}, {250, 100}, paint);
258 for (int d = 15; d < 90; d += 15) {
259 Matrix m = Matrix::MakeRotationZ(Degrees(d));
260 canvas.DrawLine(origin + m * p0, origin + m * p1, paint);
261 }
262 canvas.DrawLine({100, 150}, {100, 250}, paint);
263 canvas.DrawCircle({origin}, 35, paint);
264
265 canvas.DrawLine({250, 250}, {250, 250}, paint);
266
267 canvas.Translate({250, 0});
268 }
269 canvas.Translate({-750, 250});
270 };
271
272 std::vector<Color> colors = {
273 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
274 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
275 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
276 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
277 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
278 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
279 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
280 std::vector<Scalar> stops = {
281 0.0,
282 (1.0 / 6.0) * 1,
283 (1.0 / 6.0) * 2,
284 (1.0 / 6.0) * 3,
285 (1.0 / 6.0) * 4,
286 (1.0 / 6.0) * 5,
287 1.0,
288 };
289
290 auto texture = CreateTextureForFixture("airplane.jpg",
291 /*enable_mipmapping=*/true);
292
293 draw(paint);
294
295 paint.color_source = ColorSource::MakeRadialGradient(
296 {100, 100}, 200, std::move(colors), std::move(stops),
297 Entity::TileMode::kMirror, {});
298 draw(paint);
299
300 paint.color_source = ColorSource::MakeImage(
301 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
302 Matrix::MakeTranslation({-150, 75}));
303 draw(paint);
304
305 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
306 }

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

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

Definition at line 1928 of file aiks_unittests.cc.

1928 {
1929 Canvas canvas;
1930 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
1931 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
1932 .blend_mode = BlendMode::kSourceOver});
1933
1934 Picture picture = canvas.EndRecordingAsPicture();
1935 auto expected = Color::Red().Blend(Color::CornflowerBlue().WithAlpha(0.75),
1936 BlendMode::kSourceOver);
1937 ASSERT_EQ(picture.pass->GetClearColor(), expected);
1938
1939 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1940 std::shared_ptr<Context> real_context = GetContext();
1941 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1942 AiksContext renderer(mock_context, nullptr);
1943 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1944
1945 ASSERT_EQ(spy->render_passes_.size(), 1llu);
1946 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1947 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
1948 }

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

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

Definition at line 2804 of file aiks_unittests.cc.

2804 {
2805 if (!BackendSupportsFragmentProgram()) {
2806 GTEST_SKIP_("This backend doesn't support runtime effects.");
2807 }
2808
2809 auto runtime_stages = OpenAssetAsRuntimeStage("gradient.frag.iplr");
2810 auto runtime_stage = runtime_stages[RuntimeStageBackend::kMetal];
2811 ASSERT_TRUE(runtime_stage);
2812 ASSERT_TRUE(runtime_stage->IsDirty());
2813
2814 struct FragUniforms {
2815 Size size;
2816 } frag_uniforms = {.size = Size::MakeWH(400, 400)};
2817 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2818 uniform_data->resize(sizeof(FragUniforms));
2819 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2820
2821 std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
2822
2823 Paint paint;
2824 paint.color_source = ColorSource::MakeRuntimeEffect(
2825 runtime_stage, uniform_data, texture_inputs);
2826
2827 Canvas canvas;
2828 canvas.Save();
2829 canvas.Scale(GetContentScale());
2830 canvas.DrawPaint(paint);
2831 canvas.Restore();
2832
2833 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2834 }

References impeller::Paint::color_source, impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kMetal, impeller::ColorSource::MakeRuntimeEffect(), impeller::TSize< Scalar >::MakeWH(), impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::Canvas::Scale().

## ◆ TEST_P() [126/384]

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

Definition at line 963 of file aiks_unittests.cc.

963 {
964 Paint filtered = {
965 .color = Color::Black(),
966 .mask_blur_descriptor =
967 Paint::MaskBlurDescriptor{
968 .style = FilterContents::BlurStyle::kNormal,
969 .sigma = Sigma(60),
970 },
971 };
972
973 Canvas canvas;
974 canvas.DrawPaint({.color = Color::White()});
975 canvas.DrawCircle({300, 300}, 200, filtered);
976 canvas.DrawPaint({.color = Color::Green(), .blend_mode = BlendMode::kScreen});
977 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
978 }

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

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

Definition at line 3075 of file aiks_unittests.cc.

3075 {
3076 Canvas subcanvas;
3077 subcanvas.ClipRRect(Rect::MakeLTRB(100, 100, 400, 400), {15, 15});
3078 subcanvas.DrawPaint({.color = Color::Red()});
3079 auto picture = subcanvas.EndRecordingAsPicture();
3080
3081 Canvas canvas;
3082 canvas.DrawPaint({.color = Color::CornflowerBlue()});
3083
3084 // Draw a red RRect via DrawPicture.
3085 canvas.DrawPicture(picture);
3086
3087 // Draw over the picture with a larger green rectangle, completely covering it
3088 // up.
3089 canvas.ClipRRect(Rect::MakeLTRB(100, 100, 400, 400).Expand(20), {15, 15});
3090 canvas.DrawPaint({.color = Color::Green()});
3091
3092 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3093 }

References impeller::Canvas::ClipRRect(), impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPicture(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< T >::Expand(), impeller::Color::Green(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::Color::Red().

## ◆ TEST_P() [128/384]

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

Definition at line 3046 of file aiks_unittests.cc.

3046 {
3047 Canvas subcanvas;
3048 ASSERT_TRUE(RenderTextInCanvasSkia(
3049 GetContext(), subcanvas,
3050 "the quick brown fox jumped over the lazy dog!.?", "Roboto-Regular.ttf"));
3051 subcanvas.Translate({0, 10});
3052 subcanvas.Scale(Vector2(3, 3));
3053 ASSERT_TRUE(RenderTextInCanvasSkia(
3054 GetContext(), subcanvas,
3055 "the quick brown fox jumped over the very big lazy dog!.?",
3056 "Roboto-Regular.ttf"));
3057 auto picture = subcanvas.EndRecordingAsPicture();
3058
3059 Canvas canvas;
3060 canvas.Scale(Vector2(.2, .2));
3061 canvas.Save();
3062 canvas.Translate({200, 200});
3063 canvas.Scale(Vector2(3.5, 3.5)); // The text must not be blurry after this.
3064 canvas.DrawPicture(picture);
3065 canvas.Restore();
3066
3067 canvas.Scale(Vector2(1.5, 1.5));
3068 ASSERT_TRUE(RenderTextInCanvasSkia(
3069 GetContext(), canvas,
3070 "the quick brown fox jumped over the smaller lazy dog!.?",
3071 "Roboto-Regular.ttf"));
3072 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3073 }

References impeller::Canvas::DrawPicture(), impeller::Canvas::EndRecordingAsPicture(), RenderTextInCanvasSkia(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [129/384]

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

Definition at line 1974 of file aiks_unittests.cc.

1974 {
1975 Canvas canvas;
1976 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
1977 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
1978 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
1979 {.color = Color::CornflowerBlue().WithAlpha(0.75),
1980 .blend_mode = BlendMode::kSourceOver});
1981
1982 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1983 Picture picture = canvas.EndRecordingAsPicture();
1984 std::shared_ptr<Context> real_context = GetContext();
1985 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1986 AiksContext renderer(mock_context, nullptr);
1987 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1988
1989 ASSERT_EQ(spy->render_passes_.size(), 1llu);
1990 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1991 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
1992 }

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

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

Definition at line 2034 of file aiks_unittests.cc.

2034 {
2035 Canvas canvas;
2036 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
2037 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
2038 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
2039 {.color = Color::CornflowerBlue().WithAlpha(0.75),
2040 .blend_mode = BlendMode::kSourceOver});
2041
2042 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2043 Picture picture = canvas.EndRecordingAsPicture();
2044 std::shared_ptr<Context> real_context = GetContext();
2045 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2046 AiksContext renderer(mock_context, nullptr);
2047 std::shared_ptr<Image> image = picture.ToImage(renderer, {301, 301});
2048
2049 ASSERT_EQ(spy->render_passes_.size(), 1llu);
2050 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2051 ASSERT_EQ(render_pass->GetCommands().size(), 2llu);
2052 }

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

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

Definition at line 2014 of file aiks_unittests.cc.

2014 {
2015 Canvas canvas;
2016 canvas.Translate(Vector3(150.0, 150.0, 0.0));
2017 canvas.Rotate(Degrees(45.0));
2018 canvas.Translate(Vector3(-150.0, -150.0, 0.0));
2019 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
2020 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
2021
2022 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2023 Picture picture = canvas.EndRecordingAsPicture();
2024 std::shared_ptr<Context> real_context = GetContext();
2025 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2026 AiksContext renderer(mock_context, nullptr);
2027 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
2028
2029 ASSERT_EQ(spy->render_passes_.size(), 1llu);
2030 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2031 ASSERT_EQ(render_pass->GetCommands().size(), 1llu);
2032 }

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

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

Definition at line 1994 of file aiks_unittests.cc.

1994 {
1995 Canvas canvas;
1996 canvas.DrawRRect(Rect::MakeXYWH(0, 0, 300, 300), {5.0, 5.0},
1997 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
1998 canvas.DrawRRect(Rect::MakeXYWH(0, 0, 300, 300), {5.0, 5.0},
1999 {.color = Color::CornflowerBlue().WithAlpha(0.75),
2000 .blend_mode = BlendMode::kSourceOver});
2001
2002 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2003 Picture picture = canvas.EndRecordingAsPicture();
2004 std::shared_ptr<Context> real_context = GetContext();
2005 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2006 AiksContext renderer(mock_context, nullptr);
2007 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
2008
2009 ASSERT_EQ(spy->render_passes_.size(), 1llu);
2010 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2011 ASSERT_EQ(render_pass->GetCommands().size(), 2llu);
2012 }

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

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

Definition at line 308 of file aiks_path_unittests.cc.

308 {
309 Canvas canvas;
310 Paint paint;
311 paint.color = Color::Red();
312 paint.style = Paint::Style::kStroke;
313 paint.stroke_width = 10;
314
315 canvas.Translate({100, 100});
316 canvas.DrawPath(
317 PathBuilder{}.AddRect(Rect::MakeSize(Size{100, 100})).TakePath(),
318 {paint});
319
320 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
321 }

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

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

Definition at line 323 of file aiks_path_unittests.cc.

323 {
324 Canvas canvas;
325 Paint paint;
326 paint.color = Color::Red();
327 paint.style = Paint::Style::kStroke;
328 paint.stroke_width = 10;
329 paint.stroke_join = Join::kBevel;
330
331 canvas.Translate({100, 100});
332 canvas.DrawPath(
333 PathBuilder{}.AddRect(Rect::MakeSize(Size{100, 100})).TakePath(),
334 {paint});
335
336 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
337 }

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

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

Definition at line 3157 of file aiks_unittests.cc.

3157 {
3158 Canvas canvas;
3159 // clang-format off
3160 canvas.Transform(Matrix(
3161 2.000000, 0.000000, 0.000000, 0.000000,
3162 1.445767, 2.637070, -0.507928, 0.001524,
3163 -2.451887, -0.534662, 0.861399, -0.002584,
3164 1063.481934, 1025.951416, -48.300270, 1.144901
3165 ));
3166 // clang-format on
3167
3168 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), canvas, "Hello world",
3169 "Roboto-Regular.ttf"));
3170
3171 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3172 }

References impeller::Canvas::EndRecordingAsPicture(), RenderTextInCanvasSkia(), and impeller::Canvas::Transform().

## ◆ TEST_P() [136/384]

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

Definition at line 3174 of file aiks_unittests.cc.

3174 {
3175 Canvas canvas;
3176 Paint save_paint;
3177 canvas.SaveLayer(save_paint);
3178 // clang-format off
3179 canvas.Transform(Matrix(
3180 2.000000, 0.000000, 0.000000, 0.000000,
3181 1.445767, 2.637070, -0.507928, 0.001524,
3182 -2.451887, -0.534662, 0.861399, -0.002584,
3183 1063.481934, 1025.951416, -48.300270, 1.144901
3184 ));
3185 // clang-format on
3186
3187 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), canvas, "Hello world",
3188 "Roboto-Regular.ttf"));
3189 }

References RenderTextInCanvasSkia(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Transform().

## ◆ TEST_P() [137/384]

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

Definition at line 3474 of file aiks_unittests.cc.

3474 {
3475 Canvas canvas;
3476 canvas.Scale(GetContentScale());
3477 canvas.DrawPaint(Paint{.color = Color::Red()});
3478 canvas.ClipRect(Rect::MakeXYWH(100, 100, 200, 200));
3479 canvas.SaveLayer(Paint{.color = Color::Blue()});
3480 canvas.Restore();
3481 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3482 }

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

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

Definition at line 3484 of file aiks_unittests.cc.

3484 {
3485 Canvas canvas;
3486 canvas.Scale(GetContentScale());
3487 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
3488 canvas.DrawImage(image, {10, 10}, {});
3489 canvas.ClipRect(Rect::MakeXYWH(100, 100, 200, 200));
3490 canvas.SaveLayer(Paint{.blend_mode = BlendMode::kClear});
3491 canvas.Restore();
3492 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3493 }

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

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

Definition at line 1247 of file aiks_unittests.cc.

1247 {
1248 Canvas canvas;
1249 canvas.Scale(GetContentScale());
1250 Paint paint;
1251 const int color_count = 3;
1252 Color colors[color_count] = {
1253 Color::Blue(),
1254 Color::Green(),
1255 Color::Crimson(),
1256 };
1257
1258 paint.color = Color::White();
1259 canvas.DrawPaint(paint);
1260
1261 int c_index = 0;
1262 int radius = 600;
1263 while (radius > 0) {
1264 paint.color = colors[(c_index++) % color_count];
1265 canvas.DrawCircle({10, 10}, radius, paint);
1266 if (radius > 30) {
1267 radius -= 10;
1268 } else {
1269 radius -= 2;
1270 }
1271 }
1272
1273 std::vector<Color> gradient_colors = {
1274 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1275 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1276 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1277 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1278 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1279 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1280 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1281 std::vector<Scalar> stops = {
1282 0.0,
1283 (1.0 / 6.0) * 1,
1284 (1.0 / 6.0) * 2,
1285 (1.0 / 6.0) * 3,
1286 (1.0 / 6.0) * 4,
1287 (1.0 / 6.0) * 5,
1288 1.0,
1289 };
1290 auto texture = CreateTextureForFixture("airplane.jpg",
1291 /*enable_mipmapping=*/true);
1292
1293 paint.color_source = ColorSource::MakeRadialGradient(
1294 {500, 600}, 75, std::move(gradient_colors), std::move(stops),
1295 Entity::TileMode::kMirror, {});
1296 canvas.DrawCircle({500, 600}, 100, paint);
1297
1298 paint.color_source = ColorSource::MakeImage(
1299 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1300 Matrix::MakeTranslation({700, 200}));
1301 canvas.DrawCircle({800, 300}, 100, paint);
1302
1303 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1304 }

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

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

Definition at line 1370 of file aiks_unittests.cc.

1370 {
1371 Canvas canvas;
1372 canvas.Scale(GetContentScale());
1373 Paint paint;
1374 const int color_count = 3;
1375 Color colors[color_count] = {
1376 Color::Blue(),
1377 Color::Green(),
1378 Color::Crimson(),
1379 };
1380
1381 paint.color = Color::White();
1382 canvas.DrawPaint(paint);
1383
1384 int c_index = 0;
1385 int long_radius = 600;
1386 int short_radius = 600;
1387 while (long_radius > 0 && short_radius > 0) {
1388 paint.color = colors[(c_index++) % color_count];
1389 canvas.DrawOval(Rect::MakeXYWH(10 - long_radius, 10 - short_radius,
1390 long_radius * 2, short_radius * 2),
1391 paint);
1392 canvas.DrawOval(Rect::MakeXYWH(1000 - short_radius, 750 - long_radius,
1393 short_radius * 2, long_radius * 2),
1394 paint);
1395 if (short_radius > 30) {
1396 short_radius -= 10;
1397 long_radius -= 5;
1398 } else {
1399 short_radius -= 2;
1400 long_radius -= 1;
1401 }
1402 }
1403
1404 std::vector<Color> gradient_colors = {
1405 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1406 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1407 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1408 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1409 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1410 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1411 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1412 std::vector<Scalar> stops = {
1413 0.0,
1414 (1.0 / 6.0) * 1,
1415 (1.0 / 6.0) * 2,
1416 (1.0 / 6.0) * 3,
1417 (1.0 / 6.0) * 4,
1418 (1.0 / 6.0) * 5,
1419 1.0,
1420 };
1421 auto texture = CreateTextureForFixture("airplane.jpg",
1422 /*enable_mipmapping=*/true);
1423
1424 paint.color = Color::White().WithAlpha(0.5);
1425
1426 paint.color_source = ColorSource::MakeRadialGradient(
1427 {300, 650}, 75, std::move(gradient_colors), std::move(stops),
1428 Entity::TileMode::kMirror, {});
1429 canvas.DrawOval(Rect::MakeXYWH(200, 625, 200, 50), paint);
1430 canvas.DrawOval(Rect::MakeXYWH(275, 550, 50, 200), paint);
1431
1432 paint.color_source = ColorSource::MakeImage(
1433 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1434 Matrix::MakeTranslation({610, 15}));
1435 canvas.DrawOval(Rect::MakeXYWH(610, 90, 200, 50), paint);
1436 canvas.DrawOval(Rect::MakeXYWH(685, 15, 50, 200), paint);
1437
1438 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1439 }

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

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

Definition at line 1585 of file aiks_unittests.cc.

1585 {
1586 Canvas canvas;
1587 canvas.Scale(GetContentScale());
1588 Paint paint;
1589 const int color_count = 3;
1590 Color colors[color_count] = {
1591 Color::Blue(),
1592 Color::Green(),
1593 Color::Crimson(),
1594 };
1595
1596 paint.color = Color::White();
1597 canvas.DrawPaint(paint);
1598
1599 auto draw_rrect_as_path = [&canvas](const Rect& rect, const Size& radii,
1600 const Paint& paint) {
1601 PathBuilder builder = PathBuilder();
1602 builder.AddRoundedRect(rect, radii);
1603 canvas.DrawPath(builder.TakePath(), paint);
1604 };
1605
1606 int c_index = 0;
1607 for (int i = 0; i < 4; i++) {
1608 for (int j = 0; j < 4; j++) {
1609 paint.color = colors[(c_index++) % color_count];
1610 draw_rrect_as_path(Rect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1611 Size(i * 5 + 10, j * 5 + 10), paint);
1612 }
1613 }
1614 paint.color = colors[(c_index++) % color_count];
1615 draw_rrect_as_path(Rect::MakeXYWH(10, 420, 380, 80), Size(40, 40), paint);
1616 paint.color = colors[(c_index++) % color_count];
1617 draw_rrect_as_path(Rect::MakeXYWH(410, 20, 80, 380), Size(40, 40), paint);
1618
1619 std::vector<Color> gradient_colors = {
1620 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1621 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1622 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1623 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1624 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1625 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1626 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1627 std::vector<Scalar> stops = {
1628 0.0,
1629 (1.0 / 6.0) * 1,
1630 (1.0 / 6.0) * 2,
1631 (1.0 / 6.0) * 3,
1632 (1.0 / 6.0) * 4,
1633 (1.0 / 6.0) * 5,
1634 1.0,
1635 };
1636 auto texture = CreateTextureForFixture("airplane.jpg",
1637 /*enable_mipmapping=*/true);
1638
1639 paint.color = Color::White().WithAlpha(0.1);
1640 paint.color_source = ColorSource::MakeRadialGradient(
1641 {550, 550}, 75, gradient_colors, stops, Entity::TileMode::kMirror, {});
1642 for (int i = 1; i <= 10; i++) {
1643 int j = 11 - i;
1644 draw_rrect_as_path(Rect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1645 550 + i * 20, 550 + j * 20),
1646 Size(i * 10, j * 10), paint);
1647 }
1648 paint.color = Color::White().WithAlpha(0.5);
1649 paint.color_source = ColorSource::MakeRadialGradient(
1650 {200, 650}, 75, std::move(gradient_colors), std::move(stops),
1651 Entity::TileMode::kMirror, {});
1652 draw_rrect_as_path(Rect::MakeLTRB(100, 610, 300, 690), Size(40, 40), paint);
1653 draw_rrect_as_path(Rect::MakeLTRB(160, 550, 240, 750), Size(40, 40), paint);
1654
1655 paint.color = Color::White().WithAlpha(0.1);
1656 paint.color_source = ColorSource::MakeImage(
1657 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1658 Matrix::MakeTranslation({520, 20}));
1659 for (int i = 1; i <= 10; i++) {
1660 int j = 11 - i;
1661 draw_rrect_as_path(Rect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1662 720 + i * 20, 220 + j * 20),
1663 Size(i * 10, j * 10), paint);
1664 }
1665 paint.color = Color::White().WithAlpha(0.5);
1666 paint.color_source = ColorSource::MakeImage(
1667 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1668 Matrix::MakeTranslation({800, 300}));
1669 draw_rrect_as_path(Rect::MakeLTRB(800, 410, 1000, 490), Size(40, 40), paint);
1670 draw_rrect_as_path(Rect::MakeLTRB(860, 350, 940, 550), Size(40, 40), paint);
1671
1672 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1673 }

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

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

Definition at line 1441 of file aiks_unittests.cc.

1441 {
1442 Canvas canvas;
1443 canvas.Scale(GetContentScale());
1444 Paint paint;
1445 const int color_count = 3;
1446 Color colors[color_count] = {
1447 Color::Blue(),
1448 Color::Green(),
1449 Color::Crimson(),
1450 };
1451
1452 paint.color = Color::White();
1453 canvas.DrawPaint(paint);
1454
1455 int c_index = 0;
1456 for (int i = 0; i < 4; i++) {
1457 for (int j = 0; j < 4; j++) {
1458 paint.color = colors[(c_index++) % color_count];
1459 canvas.DrawRRect(Rect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1460 Size(i * 5 + 10, j * 5 + 10), paint);
1461 }
1462 }
1463 paint.color = colors[(c_index++) % color_count];
1464 canvas.DrawRRect(Rect::MakeXYWH(10, 420, 380, 80), Size(40, 40), paint);
1465 paint.color = colors[(c_index++) % color_count];
1466 canvas.DrawRRect(Rect::MakeXYWH(410, 20, 80, 380), Size(40, 40), paint);
1467
1468 std::vector<Color> gradient_colors = {
1469 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1470 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1471 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1472 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1473 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1474 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1475 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1476 std::vector<Scalar> stops = {
1477 0.0,
1478 (1.0 / 6.0) * 1,
1479 (1.0 / 6.0) * 2,
1480 (1.0 / 6.0) * 3,
1481 (1.0 / 6.0) * 4,
1482 (1.0 / 6.0) * 5,
1483 1.0,
1484 };
1485 auto texture = CreateTextureForFixture("airplane.jpg",
1486 /*enable_mipmapping=*/true);
1487
1488 paint.color = Color::White().WithAlpha(0.1);
1489 paint.color_source = ColorSource::MakeRadialGradient(
1490 {550, 550}, 75, gradient_colors, stops, Entity::TileMode::kMirror, {});
1491 for (int i = 1; i <= 10; i++) {
1492 int j = 11 - i;
1493 canvas.DrawRRect(Rect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1494 550 + i * 20, 550 + j * 20),
1495 Size(i * 10, j * 10), paint);
1496 }
1497 paint.color = Color::White().WithAlpha(0.5);
1498 paint.color_source = ColorSource::MakeRadialGradient(
1499 {200, 650}, 75, std::move(gradient_colors), std::move(stops),
1500 Entity::TileMode::kMirror, {});
1501 canvas.DrawRRect(Rect::MakeLTRB(100, 610, 300, 690), Size(40, 40), paint);
1502 canvas.DrawRRect(Rect::MakeLTRB(160, 550, 240, 750), Size(40, 40), paint);
1503
1504 paint.color = Color::White().WithAlpha(0.1);
1505 paint.color_source = ColorSource::MakeImage(
1506 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1507 Matrix::MakeTranslation({520, 20}));
1508 for (int i = 1; i <= 10; i++) {
1509 int j = 11 - i;
1510 canvas.DrawRRect(Rect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1511 720 + i * 20, 220 + j * 20),
1512 Size(i * 10, j * 10), paint);
1513 }
1514 paint.color = Color::White().WithAlpha(0.5);
1515 paint.color_source = ColorSource::MakeImage(
1516 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1517 Matrix::MakeTranslation({800, 300}));
1518 canvas.DrawRRect(Rect::MakeLTRB(800, 410, 1000, 490), Size(40, 40), paint);
1519 canvas.DrawRRect(Rect::MakeLTRB(860, 350, 940, 550), Size(40, 40), paint);
1520
1521 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1522 }

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

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

Definition at line 2132 of file aiks_unittests.cc.

2132 {
2133 Canvas canvas;
2134
2135 canvas.SaveLayer({
2136 .color_filter =
2137 ColorFilter::MakeBlend(BlendMode::kColorDodge, Color::Red()),
2138 });
2139
2140 canvas.Translate({500, 300, 0});
2141 canvas.Rotate(Radians(2 * kPi / 3));
2142 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
2143
2144 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2145 }

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

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

Definition at line 3581 of file aiks_unittests.cc.

3581 {
3582 Canvas canvas;
3583
3584 canvas.Scale(GetContentScale());
3585 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
3586 canvas.DrawImageRect(
3587 std::make_shared<Image>(boston),
3588 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
3589 Rect::MakeLTRB(0, 0, GetWindowSize().width, 100), Paint{});
3590 canvas.DrawRRect(Rect::MakeLTRB(0, 110, GetWindowSize().width, 210),
3591 Size(10, 10), Paint{.color = Color::Magenta()});
3592 canvas.ClipRect(Rect::MakeLTRB(0, 50, GetWindowSize().width, 150));
3593 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
3594 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
3595 FilterContents::BlurStyle::kNormal,
3596 Entity::TileMode::kClamp));
3597 canvas.Restore();
3598 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3599 }

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

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

Definition at line 3563 of file aiks_unittests.cc.

3563 {
3564 Canvas canvas;
3565
3566 canvas.Scale(GetContentScale());
3567 canvas.DrawRRect(Rect::MakeLTRB(0, 0, GetWindowSize().width, 100),
3568 Size(10, 10), Paint{.color = Color::LimeGreen()});
3569 canvas.DrawRRect(Rect::MakeLTRB(0, 110, GetWindowSize().width, 210),
3570 Size(10, 10), Paint{.color = Color::Magenta()});
3571 canvas.ClipRect(Rect::MakeLTRB(100, 0, 200, GetWindowSize().height));
3572 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
3573 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
3574 FilterContents::BlurStyle::kNormal,
3575 Entity::TileMode::kClamp));
3576 canvas.Restore();
3577
3578 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3579 }

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

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

Definition at line 3650 of file aiks_unittests.cc.

3650 {
3651 Canvas canvas;
3652
3653 canvas.Scale(GetContentScale());
3654 canvas.Scale({0.5, 0.5, 1.0});
3655 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
3656 canvas.DrawImage(std::make_shared<Image>(boston), Point(100, 100), Paint{});
3657 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
3658 ImageFilter::MakeBlur(Sigma(50.0), Sigma(0.0),
3659 FilterContents::BlurStyle::kNormal,
3660 Entity::TileMode::kClamp));
3661 canvas.Restore();
3662 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3663 }

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

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

Definition at line 3669 of file aiks_unittests.cc.

3669 {
3670 Canvas canvas;
3671 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
3672 Rect bounds =
3673 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
3674 Vector2 image_center = Vector2(bounds.GetSize() / 2);
3675 Paint paint = {.image_filter =
3676 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
3677 FilterContents::BlurStyle::kNormal,
3678 Entity::TileMode::kDecal)};
3679 Vector2 clip_size = {150, 75};
3680 Vector2 center = Vector2(1024, 768) / 2;
3681 canvas.Scale(GetContentScale());
3682 canvas.ClipRect(
3683 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size));
3684 canvas.Translate({center.x, center.y, 0});
3685 canvas.Scale({0.6, 0.6, 1});
3686 canvas.Rotate(Degrees(25));
3687
3688 canvas.DrawImageRect(std::make_shared<Image>(boston), /*source=*/bounds,
3689 /*dest=*/bounds.Shift(-image_center), paint);
3690
3691 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3692 }

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

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

Definition at line 3718 of file aiks_unittests.cc.

3718 {
3719 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
3720
3721 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
3722 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
3723 const Entity::TileMode tile_modes[] = {
3724 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
3725 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
3726
3727 static float rotation = 0;
3728 static float scale = 0.6;
3729 static int selected_tile_mode = 3;
3730
3731 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
3732 {
3733 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
3734 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
3735 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
3736 sizeof(tile_mode_names) / sizeof(char*));
3737 }
3738 ImGui::End();
3739
3740 Canvas canvas;
3741 Rect bounds =
3742 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
3743 Vector2 image_center = Vector2(bounds.GetSize() / 2);
3744 Paint paint = {.image_filter =
3745 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
3746 FilterContents::BlurStyle::kNormal,
3747 tile_modes[selected_tile_mode])};
3748 auto [handle_a, handle_b] = IMPELLER_PLAYGROUND_LINE(
3749 Point(362, 309), Point(662, 459), 20, Color::Red(), Color::Red());
3750 Vector2 center = Vector2(1024, 768) / 2;
3751 canvas.Scale(GetContentScale());
3752 canvas.ClipRect(
3753 Rect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
3754 canvas.Translate({center.x, center.y, 0});
3755 canvas.Scale({scale, scale, 1});
3756 canvas.Rotate(Degrees(rotation));
3757
3758 canvas.DrawImageRect(std::make_shared<Image>(boston), /*source=*/bounds,
3759 /*dest=*/bounds.Shift(-image_center), paint);
3760 return canvas.EndRecordingAsPicture();
3761 };
3762
3763 ASSERT_TRUE(OpenPlaygroundHere(callback));
3764 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawImageRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< T >::GetSize(), impeller::Paint::image_filter, IMPELLER_PLAYGROUND_LINE, 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(), impeller::TRect< T >::Shift(), impeller::Canvas::Translate(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [149/384]

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

Definition at line 3694 of file aiks_unittests.cc.

3694 {
3695 Canvas canvas;
3696 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
3697 Rect bounds =
3698 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
3699 Vector2 image_center = Vector2(bounds.GetSize() / 2);
3700 Paint paint = {.image_filter =
3701 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
3702 FilterContents::BlurStyle::kNormal,
3703 Entity::TileMode::kDecal)};
3704 Vector2 clip_size = {150, 75};
3705 Vector2 center = Vector2(1024, 768) / 2;
3706 canvas.Scale(GetContentScale());
3707 canvas.ClipRect(
3708 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size));
3709 canvas.Translate({center.x, center.y, 0});
3710 canvas.Scale({0.6, 0.6, 1});
3711
3712 canvas.DrawImageRect(std::make_shared<Image>(boston), /*source=*/bounds,
3713 /*dest=*/bounds.Shift(-image_center), paint);
3714
3715 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3716 }

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

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

Definition at line 3605 of file aiks_unittests.cc.

3605 {
3606 if (GetParam() != PlaygroundBackend::kMetal) {
3607 GTEST_SKIP_(
3608 "This backend doesn't yet support setting device capabilities.");
3609 }
3610 if (!WillRenderSomething()) {
3611 // Sometimes these tests are run without playgrounds enabled which is
3612 // pointless for this test since we are asserting that
3613 // `SupportsDecalSamplerAddressMode` is called.
3614 GTEST_SKIP_("This test requires playgrounds.");
3615 }
3616
3617 std::shared_ptr<const Capabilities> old_capabilities =
3618 GetContext()->GetCapabilities();
3619 auto mock_capabilities = std::make_shared<MockCapabilities>();
3620 EXPECT_CALL(*mock_capabilities, SupportsDecalSamplerAddressMode())
3621 .Times(::testing::AtLeast(1))
3622 .WillRepeatedly(::testing::Return(false));
3623 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultColorFormat);
3624 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultStencilFormat);
3625 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsOffscreenMSAA);
3626 FLT_FORWARD(mock_capabilities, old_capabilities,
3627 SupportsImplicitResolvingMSAA);
3628 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsReadFromResolve);
3629 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsFramebufferFetch);
3630 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsSSBO);
3631 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsCompute);
3632 FLT_FORWARD(mock_capabilities, old_capabilities,
3633 SupportsTextureToTextureBlits);
3634 ASSERT_TRUE(SetCapabilities(mock_capabilities).ok());
3635
3636 auto texture = std::make_shared<Image>(CreateTextureForFixture("boston.jpg"));
3637 Canvas canvas;
3638 canvas.Scale(GetContentScale() * 0.5);
3639 canvas.DrawPaint({.color = Color::Black()});
3640 canvas.DrawImage(
3641 texture, Point(200, 200),
3642 {
3643 .image_filter = ImageFilter::MakeBlur(
3644 Sigma(20.0), Sigma(20.0), FilterContents::BlurStyle::kNormal,
3645 Entity::TileMode::kDecal),
3646 });
3647 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3648 }

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

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

Definition at line 651 of file aiks_gradient_unittests.cc.

651 {
652 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
653 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
654 static float scale = 3;
655 static bool add_circle_clip = true;
656 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
657 const Entity::TileMode tile_modes[] = {
658 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
659 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
660 static int selected_tile_mode = 0;
661 static float alpha = 1;
662
663 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
664 ImGui::SliderFloat("Scale", &scale, 0, 6);
665 ImGui::Checkbox("Circle clip", &add_circle_clip);
666 ImGui::SliderFloat("Alpha", &alpha, 0, 1);
667 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
668 sizeof(tile_mode_names) / sizeof(char*));
669 ImGui::End();
670
671 Canvas canvas;
672 canvas.Scale(GetContentScale());
673 Paint paint;
674 paint.color = Color::White();
675 canvas.DrawPaint(paint);
676
677 paint.style = Paint::Style::kStroke;
678 paint.color = Color(1.0, 1.0, 1.0, alpha);
679 paint.stroke_width = 10;
680 auto tile_mode = tile_modes[selected_tile_mode];
681
682 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
683 Color{0.1294, 0.5882, 0.9529, 1.0}};
684 std::vector<Scalar> stops = {0.0, 1.0};
685
686 paint.color_source = ColorSource::MakeLinearGradient(
687 {0, 0}, {50, 50}, std::move(colors), std::move(stops), tile_mode, {});
688
689 Path path = PathBuilder{}
690 .MoveTo({20, 20})
691 .QuadraticCurveTo({60, 20}, {60, 60})
692 .Close()
693 .MoveTo({60, 20})
694 .QuadraticCurveTo({60, 60}, {20, 60})
695 .TakePath();
696
697 canvas.Scale(Vector2(scale, scale));
698
699 if (add_circle_clip) {
700 auto [handle_a, handle_b] = IMPELLER_PLAYGROUND_LINE(
701 Point(60, 300), Point(600, 300), 20, Color::Red(), Color::Red());
702
703 auto screen_to_canvas = canvas.GetCurrentTransform().Invert();
704 Point point_a = screen_to_canvas * handle_a * GetContentScale();
705 Point point_b = screen_to_canvas * handle_b * GetContentScale();
706
707 Point middle = (point_a + point_b) / 2;
708 auto radius = point_a.GetDistance(middle);
709 canvas.ClipPath(PathBuilder{}.AddCircle(middle, radius).TakePath());
710 }
711
712 for (auto join : {Join::kBevel, Join::kRound, Join::kMiter}) {
713 paint.stroke_join = join;
714 for (auto cap : {Cap::kButt, Cap::kSquare, Cap::kRound}) {
715 paint.stroke_cap = cap;
716 canvas.DrawPath(path.Clone(), paint);
717 canvas.Translate({80, 0});
718 }
719 canvas.Translate({-240, 60});
720 }
721
722 return canvas.EndRecordingAsPicture();
723 };
724
725 ASSERT_TRUE(OpenPlaygroundHere(callback));
726 }

References impeller::PathBuilder::AddCircle(), impeller::Canvas::ClipPath(), impeller::Close(), impeller::Paint::color, impeller::Paint::color_source, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::GetCurrentTransform(), impeller::TPoint< T >::GetDistance(), IMPELLER_PLAYGROUND_LINE, 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(), 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() [152/384]

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

Definition at line 2350 of file aiks_unittests.cc.

2350 {
2351 Canvas canvas;
2352 canvas.Scale(GetContentScale());
2353
2354 auto test = [&canvas](const std::shared_ptr<ImageFilter>& filter) {
2355 auto DrawLine = [&canvas](const Point& p0, const Point& p1,
2356 const Paint& p) {
2357 auto path = PathBuilder{}
2358 .AddLine(p0, p1)
2359 .SetConvexity(Convexity::kConvex)
2360 .TakePath();
2361 Paint paint = p;
2362 paint.style = Paint::Style::kStroke;
2363 canvas.DrawPath(std::move(path), paint);
2364 };
2365 // Registration marks for the edge of the SaveLayer
2366 DrawLine(Point(75, 100), Point(225, 100), {.color = Color::White()});
2367 DrawLine(Point(75, 200), Point(225, 200), {.color = Color::White()});
2368 DrawLine(Point(100, 75), Point(100, 225), {.color = Color::White()});
2369 DrawLine(Point(200, 75), Point(200, 225), {.color = Color::White()});
2370
2371 canvas.SaveLayer({.image_filter = filter},
2372 Rect::MakeLTRB(100, 100, 200, 200));
2373 {
2374 // DrawPaint to verify correct behavior when the contents are unbounded.
2375 canvas.DrawPaint({.color = Color::Yellow()});
2376
2377 // Contrasting rectangle to see interior blurring
2378 canvas.DrawRect(Rect::MakeLTRB(125, 125, 175, 175),
2379 {.color = Color::Blue()});
2380 }
2381 canvas.Restore();
2382 };
2383
2384 test(ImageFilter::MakeBlur(Sigma{10.0}, Sigma{10.0},
2385 FilterContents::BlurStyle::kNormal,
2386 Entity::TileMode::kDecal));
2387
2388 canvas.Translate({200.0, 0.0});
2389
2390 test(ImageFilter::MakeDilate(Radius{10.0}, Radius{10.0}));
2391
2392 canvas.Translate({200.0, 0.0});
2393
2394 test(ImageFilter::MakeErode(Radius{10.0}, Radius{10.0}));
2395
2396 canvas.Translate({-400.0, 200.0});
2397
2398 auto rotate_filter =
2399 ImageFilter::MakeMatrix(Matrix::MakeTranslation({150, 150}) *
2400 Matrix::MakeRotationZ(Degrees{10.0}) *
2401 Matrix::MakeTranslation({-150, -150}),
2402 SamplerDescriptor{});
2403 test(rotate_filter);
2404
2405 canvas.Translate({200.0, 0.0});
2406
2407 auto rgb_swap_filter = ImageFilter::MakeFromColorFilter(
2408 *ColorFilter::MakeMatrix({.array = {
2409 0, 1, 0, 0, 0, //
2410 0, 0, 1, 0, 0, //
2411 1, 0, 0, 0, 0, //
2412 0, 0, 0, 1, 0 //
2413 }}));
2414 test(rgb_swap_filter);
2415
2416 canvas.Translate({200.0, 0.0});
2417
2418 test(ImageFilter::MakeCompose(*rotate_filter, *rgb_swap_filter));
2419
2420 canvas.Translate({-400.0, 200.0});
2421
2422 test(ImageFilter::MakeLocalMatrix(Matrix::MakeTranslation({25.0, 25.0}),
2423 *rotate_filter));
2424
2425 canvas.Translate({200.0, 0.0});
2426
2427 test(ImageFilter::MakeLocalMatrix(Matrix::MakeTranslation({25.0, 25.0}),
2428 *rgb_swap_filter));
2429
2430 canvas.Translate({200.0, 0.0});
2431
2432 test(ImageFilter::MakeLocalMatrix(
2433 Matrix::MakeTranslation({25.0, 25.0}),
2434 *ImageFilter::MakeCompose(*rotate_filter, *rgb_swap_filter)));
2435
2436 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2437 }

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

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

Definition at line 2439 of file aiks_unittests.cc.

2439 {
2440 Canvas canvas;
2441 canvas.Scale(GetContentScale());
2442
2443 auto blur_filter = ImageFilter::MakeBlur(Sigma{10.0}, Sigma{10.0},
2444 FilterContents::BlurStyle::kNormal,
2445 Entity::TileMode::kDecal);
2446
2447 canvas.SaveLayer({.image_filter = blur_filter}, std::nullopt);
2448 {
2449 // DrawPaint to verify correct behavior when the contents are unbounded.
2450 canvas.DrawPaint({.color = Color::Yellow()});
2451
2452 // Contrasting rectangle to see interior blurring
2453 canvas.DrawRect(Rect::MakeLTRB(125, 125, 175, 175),
2454 {.color = Color::Blue()});
2455 }
2456 canvas.Restore();
2457
2458 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2459 }

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

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

Definition at line 2168 of file aiks_unittests.cc.

2168 {
2169 Canvas canvas;
2170
2171 canvas.SaveLayer({
2172 .color_filter = ColorFilter::MakeLinearToSrgb(),
2173 });
2174
2175 canvas.Translate({500, 300, 0});
2176 canvas.Rotate(Radians(2 * kPi / 3));
2177 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
2178
2179 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2180 }

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

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

Definition at line 3545 of file aiks_unittests.cc.

3545 {
3546 Canvas canvas;
3547
3548 Paint paint = {
3549 .color = Color::Blue(),
3550 .mask_blur_descriptor =
3551 Paint::MaskBlurDescriptor{
3552 .style = FilterContents::BlurStyle::kNormal,
3553 .sigma = Sigma(0),
3554 },
3555 };
3556
3557 canvas.DrawCircle({300, 300}, 200, paint);
3558 canvas.DrawRect(Rect::MakeLTRB(100, 300, 500, 600), paint);
3559
3560 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3561 }

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

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

Definition at line 3122 of file aiks_unittests.cc.

3122 {
3123 Canvas canvas;
3124 canvas.DrawPaint({.color = Color::Black()});
3125 canvas.SaveLayer({}, std::nullopt);
3126 {
3127 canvas.DrawCircle(Point(200, 200), 100,
3128 {.color = Color::Green().WithAlpha(0.5),
3129 .blend_mode = BlendMode::kPlus});
3130 // Should render a second circle, centered on the bottom-right-most edge of
3131 // the circle.
3132 canvas.SaveLayer(
3133 {}, std::nullopt,
3134 ImageFilter::MakeMatrix(
3135 Matrix::MakeTranslation(Vector2(1, 1) * (100 + 100 * k1OverSqrt2)) *
3136 Matrix::MakeScale(Vector2(1, 1) * 0.5) *
3137 Matrix::MakeTranslation(Vector2(-100, -100)),
3138 SamplerDescriptor{}));
3139 canvas.Restore();
3140 }
3141 canvas.Restore();
3142
3143 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3144 }

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

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

Definition at line 3420 of file aiks_unittests.cc.

3421 {
3422 Canvas canvas;
3423 canvas.Scale(GetContentScale());
3424 canvas.Translate({100, 100});
3425 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
3426 // +300 translation applied by a SaveLayer image filter.
3427 canvas.SaveLayer({
3428 .image_filter = std::make_shared<MatrixImageFilter>(
3429 Matrix::MakeTranslation({300, 0}) * Matrix::MakeScale({2, 2, 2}),
3430 SamplerDescriptor{}),
3431 });
3432 canvas.DrawCircle({-150, 0}, 50, {.color = Color::Green()});
3433 canvas.Restore();
3434
3435 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3436 }

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

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

Definition at line 3403 of file aiks_unittests.cc.

3403 {
3404 Canvas canvas;
3405 canvas.Scale(GetContentScale());
3406 canvas.Translate({100, 100});
3407 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
3408 // +300 translation applied by a SaveLayer image filter.
3409 canvas.SaveLayer({
3410 .image_filter = std::make_shared<MatrixImageFilter>(
3411 Matrix::MakeTranslation({300, 0}), SamplerDescriptor{}),
3412 });
3413 canvas.DrawCircle({-300, 0}, 100, {.color = Color::Green()});
3414 canvas.Restore();
3415
3416 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3417 }

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

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

Definition at line 3386 of file aiks_unittests.cc.

3386 {
3387 Canvas canvas;
3388 canvas.Scale(GetContentScale());
3389 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
3390 canvas.Translate({600, -200});
3391 canvas.SaveLayer({
3392 .image_filter = std::make_shared<MatrixImageFilter>(
3393 Matrix::MakeScale({2, 2, 2}), SamplerDescriptor{}),
3394 });
3395 canvas.DrawImage(image, {0, 0},
3396 Paint{.color = Color::White().WithAlpha(0.5)});
3397 canvas.Restore();
3398
3399 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3400 }

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

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

Definition at line 3095 of file aiks_unittests.cc.

3095 {
3096 Canvas canvas;
3097 canvas.DrawPaint({.color = Color::Black()});
3098 canvas.SaveLayer({}, std::nullopt);
3099 {
3100 canvas.DrawCircle(Point(200, 200), 100,
3101 {.color = Color::Green().WithAlpha(0.5),
3102 .blend_mode = BlendMode::kPlus});
3103 // Should render a second circle, centered on the bottom-right-most edge of
3104 // the circle.
3105 canvas.SaveLayer({.image_filter = ImageFilter::MakeMatrix(
3106 Matrix::MakeTranslation(Vector2(1, 1) *
3107 (200 + 100 * k1OverSqrt2)) *
3108 Matrix::MakeScale(Vector2(1, 1) * 0.5) *
3109 Matrix::MakeTranslation(Vector2(-200, -200)),
3110 SamplerDescriptor{})},
3111 std::nullopt);
3112 canvas.DrawCircle(Point(200, 200), 100,
3113 {.color = Color::Green().WithAlpha(0.5),
3114 .blend_mode = BlendMode::kPlus});
3115 canvas.Restore();
3116 }
3117 canvas.Restore();
3118
3119 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3120 }

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

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

Definition at line 1889 of file aiks_unittests.cc.

1889 {
1890 auto entity_pass = std::make_shared<EntityPass>();
1891 auto rect = Rect::MakeLTRB(0, 0, 100, 100);
1892 Paint paint;
1893 paint.color = Color::White().WithAlpha(0.5);
1894 paint.color_filter =
1895 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Blue());
1896
1897 // Paint has color filter, can't elide.
1898 auto delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
1899 ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
1900
1901 paint.color_filter = nullptr;
1902 paint.image_filter = ImageFilter::MakeBlur(Sigma(1.0), Sigma(1.0),
1903 FilterContents::BlurStyle::kNormal,
1904 Entity::TileMode::kClamp);
1905
1906 // Paint has image filter, can't elide.
1907 delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
1908 ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
1909
1910 paint.image_filter = nullptr;
1911 paint.color = Color::Red();
1912
1913 // Paint has no alpha, can't elide;
1914 delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
1915 ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
1916
1917 // Positive test.
1918 Entity entity;
1919 entity.SetContents(SolidColorContents::Make(
1920 PathBuilder{}.AddRect(rect).TakePath(), Color::Red()));
1921 entity_pass->AddEntity(std::move(entity));
1922 paint.color = Color::Red().WithAlpha(0.5);
1923
1924 delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
1925 ASSERT_TRUE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
1926 }

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

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

Definition at line 2601 of file aiks_unittests.cc.

2601 {
2602 Canvas canvas;
2603 canvas.Scale(Vector2(1.618, 1.618));
2604 canvas.DrawCircle(Point(), 10,
2605 {
2606 .color = Color::CornflowerBlue(),
2607 .blend_mode = BlendMode::kSourceOver,
2608 });
2609 Picture picture = canvas.EndRecordingAsPicture();
2610
2611 // Extract the SolidColorSource.
2612 // Entity entity;
2613 std::vector<Entity> entity;
2614 std::shared_ptr<SolidColorContents> contents;
2615 picture.pass->IterateAllEntities([e = &entity, &contents](Entity& entity) {
2616 if (ScalarNearlyEqual(entity.GetTransform().GetScale().x, 1.618f)) {
2617 contents =
2618 std::static_pointer_cast<SolidColorContents>(entity.GetContents());
2619 e->emplace_back(entity.Clone());
2620 return false;
2621 }
2622 return true;
2623 });
2624
2625 ASSERT_TRUE(entity.size() >= 1);
2626 ASSERT_TRUE(contents->IsOpaque());
2627 ASSERT_EQ(entity[0].GetBlendMode(), BlendMode::kSource);
2628 }

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

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

Definition at line 1053 of file aiks_unittests.cc.

1053 {
1054 Paint paint;
1055 Canvas canvas;
1056 // Default is kSourceOver.
1057 paint.color = Color(1, 0, 0, 0.5);
1058 canvas.DrawCircle(Point(150, 200), 100, paint);
1059 paint.color = Color(0, 1, 0, 0.5);
1060 canvas.DrawCircle(Point(250, 200), 100, paint);
1061
1062 paint.blend_mode = BlendMode::kPlus;
1063 paint.color = Color::Red();
1064 canvas.DrawCircle(Point(450, 250), 100, paint);
1065 paint.color = Color::Green();
1066 canvas.DrawCircle(Point(550, 250), 100, paint);
1067 paint.color = Color::Blue();
1068 canvas.DrawCircle(Point(500, 150), 100, paint);
1069 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1070 }

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

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

Definition at line 1862 of file aiks_unittests.cc.

1862 {
1863 // validate that a paint with a color filter "HasFilters", no other filters
1864 // impact this setting.
1865 Paint paint;
1866
1867 ASSERT_FALSE(paint.HasColorFilter());
1868
1869 paint.color_filter =
1870 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Blue());
1871
1872 ASSERT_TRUE(paint.HasColorFilter());
1873
1874 paint.image_filter = ImageFilter::MakeBlur(Sigma(1.0), Sigma(1.0),
1875 FilterContents::BlurStyle::kNormal,
1876 Entity::TileMode::kClamp);
1877
1878 ASSERT_TRUE(paint.HasColorFilter());
1879
1880 paint.mask_blur_descriptor = {};
1881
1882 ASSERT_TRUE(paint.HasColorFilter());
1883
1884 paint.color_filter = nullptr;
1885
1886 ASSERT_FALSE(paint.HasColorFilter());
1887 }

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

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

Definition at line 1952 of file aiks_unittests.cc.

1953 {
1954 Canvas canvas;
1955 canvas.SaveLayer({}, std::nullopt, ImageFilter::MakeMatrix(Matrix(), {}));
1956 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
1957 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
1958 .blend_mode = BlendMode::kSourceOver});
1959 canvas.Restore();
1960
1961 Picture picture = canvas.EndRecordingAsPicture();
1962
1963 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1964 std::shared_ptr<Context> real_context = GetContext();
1965 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1966 AiksContext renderer(mock_context, nullptr);
1967 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1968
1969 ASSERT_EQ(spy->render_passes_.size(), 3llu);
1970 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1971 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
1972 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), 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() [166/384]

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

Definition at line 3191 of file aiks_unittests.cc.

3191 {
3192 Canvas canvas;
3193
3194 // Should render a green square in the middle of a blue circle.
3195 canvas.SaveLayer({});
3196 {
3197 canvas.Translate(Point(100, 100));
3198 canvas.DrawCircle(Point(200, 200), 200, {.color = Color::Blue()});
3199 canvas.ClipRect(Rect::MakeXYWH(100, 100, 200, 200));
3200 canvas.DrawCircle(Point(200, 200), 200,
3201 {
3202 .color = Color::Green(),
3203 .blend_mode = BlendMode::kSourceOver,
3204 .image_filter = ImageFilter::MakeFromColorFilter(
3205 *ColorFilter::MakeBlend(BlendMode::kDestination,
3206 Color::White())),
3207 });
3208 canvas.Restore();
3209 }
3210
3211 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3212 }

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

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

Definition at line 3279 of file aiks_unittests.cc.

3279 {
3280 auto context = GetContext();
3281 std::weak_ptr<Texture> weak_texture;
3282
3283 {
3284 auto texture = CreateTextureForFixture("table_mountain_nx.png");
3285
3286 Canvas canvas;
3287 canvas.Scale(GetContentScale());
3288 canvas.Translate({100.0f, 100.0f, 0});
3289
3290 Paint paint;
3291 paint.color_source = ColorSource::MakeImage(
3292 texture, Entity::TileMode::kClamp, Entity::TileMode::kClamp, {}, {});
3293 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
3294
3295 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3296 }
3297
3298 // See https://github.com/flutter/flutter/issues/134751.
3299 //
3300 // If the fence waiter was working this may not be released by the end of the
3301 // scope above. Adding a manual shutdown so that future changes to the fence
3302 // waiter will not flake this test.
3303 context->Shutdown();
3304
3305 // The texture should be released by now.
3306 ASSERT_TRUE(weak_texture.expired()) << "When the texture is no longer in use "
3307 "by the backend, it should be "
3308 "released.";
3309 }

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

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(std::move(arrow_stem), paint);
41 canvas.DrawPath(std::move(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() [169/384]

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

Definition at line 1712 of file aiks_unittests.cc.

1712 {
1713 // Compare with https://fiddle.skia.org/c/9e03de8567ffb49e7e83f53b64bcf636
1714 Canvas canvas;
1715 Paint paint;
1716
1717 paint.color = Color::Black();
1718 Rect rect = Rect::MakeXYWH(25, 25, 25, 25);
1719 canvas.DrawRect(rect, paint);
1720
1721 canvas.Translate({10, 10});
1722 canvas.SaveLayer({});
1723
1724 paint.color = Color::Green();
1725 canvas.DrawRect(rect, paint);
1726
1727 canvas.Restore();
1728
1729 canvas.Translate({10, 10});
1730 paint.color = Color::Red();
1731 canvas.DrawRect(rect, paint);
1732
1733 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1734 }

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

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

Definition at line 1793 of file aiks_unittests.cc.

1793 {
1794 Canvas canvas;
1795 canvas.Scale(GetContentScale());
1796 canvas.Translate(Vector2(100, 100));
1797
1798 auto texture = std::make_shared<Image>(CreateTextureForFixture("boston.jpg"));
1799 auto draw_image_layer = [&canvas, &texture](const Paint& paint) {
1800 canvas.SaveLayer(paint);
1801 canvas.DrawImage(texture, {}, Paint{});
1802 canvas.Restore();
1803 };
1804
1805 Paint effect_paint;
1806 effect_paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
1807 .style = FilterContents::BlurStyle::kNormal,
1808 .sigma = Sigma{6},
1809 };
1810 draw_image_layer(effect_paint);
1811
1812 canvas.Translate(Vector2(300, 300));
1813 canvas.Scale(Vector2(3, 3));
1814 draw_image_layer(effect_paint);
1815
1816 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1817 }

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

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

Definition at line 1736 of file aiks_unittests.cc.

1736 {
1737 Canvas canvas;
1738 Paint paint;
1739 Rect rect = Rect::MakeXYWH(0, 0, 1000, 1000);
1740
1741 // Black, green, and red squares offset by [10, 10].
1742 {
1743 canvas.SaveLayer({}, Rect::MakeXYWH(25, 25, 25, 25));
1744 paint.color = Color::Black();
1745 canvas.DrawRect(rect, paint);
1746 canvas.Restore();
1747 }
1748
1749 {
1750 canvas.SaveLayer({}, Rect::MakeXYWH(35, 35, 25, 25));
1751 paint.color = Color::Green();
1752 canvas.DrawRect(rect, paint);
1753 canvas.Restore();
1754 }
1755
1756 {
1757 canvas.SaveLayer({}, Rect::MakeXYWH(45, 45, 25, 25));
1758 paint.color = Color::Red();
1759 canvas.DrawRect(rect, paint);
1760 canvas.Restore();
1761 }
1762
1763 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1764 }

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

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

Definition at line 3146 of file aiks_unittests.cc.

3146 {
3147 auto contents = SolidColorContents();
3148 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.75));
3149 auto result = contents.ApplyColorFilter([](const Color& color) {
3150 return color.Blend(Color::LimeGreen().WithAlpha(0.75), BlendMode::kScreen);
3151 });
3152 ASSERT_TRUE(result);
3153 ASSERT_COLOR_NEAR(contents.GetColor(),
3154 Color(0.433247, 0.879523, 0.825324, 0.75));
3155 }

References ASSERT_COLOR_NEAR, impeller::Color::Blend(), impeller::Color::CornflowerBlue(), impeller::kScreen, and impeller::Color::LimeGreen().

## ◆ TEST_P() [173/384]

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

Definition at line 1524 of file aiks_unittests.cc.

1524 {
1525 Canvas canvas;
1526 canvas.Scale(GetContentScale());
1527 Paint paint;
1528 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
1529 .style = FilterContents::BlurStyle::kNormal,
1530 .sigma = Sigma{1},
1531 };
1532
1533 canvas.DrawPaint({.color = Color::White()});
1534
1535 paint.color = Color::Crimson();
1536 Scalar y = 100.0f;
1537 for (int i = 0; i < 5; i++) {
1538 Scalar x = (i + 1) * 100;
1539 Scalar radius = x / 10.0f;
1540 canvas.DrawRect(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1541 radius, 60.0f - radius),
1542 paint);
1543 }
1544
1545 paint.color = Color::Blue();
1546 y += 100.0f;
1547 for (int i = 0; i < 5; i++) {
1548 Scalar x = (i + 1) * 100;
1549 Scalar radius = x / 10.0f;
1550 canvas.DrawCircle({x + 25, y + 25}, radius, paint);
1551 }
1552
1553 paint.color = Color::Green();
1554 y += 100.0f;
1555 for (int i = 0; i < 5; i++) {
1556 Scalar x = (i + 1) * 100;
1557 Scalar radius = x / 10.0f;
1558 canvas.DrawOval(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1559 radius, 60.0f - radius),
1560 paint);
1561 }
1562
1563 paint.color = Color::Purple();
1564 y += 100.0f;
1565 for (int i = 0; i < 5; i++) {
1566 Scalar x = (i + 1) * 100;
1567 Scalar radius = x / 20.0f;
1568 canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
1569 {radius, radius}, //
1570 paint);
1571 }
1572
1573 paint.color = Color::Orange();
1574 y += 100.0f;
1575 for (int i = 0; i < 5; i++) {
1576 Scalar x = (i + 1) * 100;
1577 Scalar radius = x / 20.0f;
1578 canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
1579 {radius, 5.0f}, paint);
1580 }
1581
1582 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1583 }

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

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 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
189 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
190 ImGui::SliderFloat("Scale", &scale, 0, 6);
191 ImGui::Checkbox("Circle clip", &add_circle_clip);
192 ImGui::End();
193
194 Canvas canvas;
195 canvas.Scale(GetContentScale());
196 Paint paint;
197
198 paint.color = Color::White();
199 canvas.DrawPaint(paint);
200
201 paint.color = color;
202 paint.style = Paint::Style::kStroke;
203 paint.stroke_width = 10;
204
205 Path path = PathBuilder{}
206 .MoveTo({20, 20})
207 .QuadraticCurveTo({60, 20}, {60, 60})
208 .Close()
209 .MoveTo({60, 20})
210 .QuadraticCurveTo({60, 60}, {20, 60})
211 .TakePath();
212
213 canvas.Scale(Vector2(scale, scale));
214
215 if (add_circle_clip) {
216 auto [handle_a, handle_b] = IMPELLER_PLAYGROUND_LINE(
217 Point(60, 300), Point(600, 300), 20, Color::Red(), Color::Red());
218
219 auto screen_to_canvas = canvas.GetCurrentTransform().Invert();
220 Point point_a = screen_to_canvas * handle_a * GetContentScale();
221 Point point_b = screen_to_canvas * handle_b * GetContentScale();
222
223 Point middle = (point_a + point_b) / 2;
224 auto radius = point_a.GetDistance(middle);
225 canvas.ClipPath(PathBuilder{}.AddCircle(middle, radius).TakePath());
226 }
227
228 for (auto join : {Join::kBevel, Join::kRound, Join::kMiter}) {
229 paint.stroke_join = join;
230 for (auto cap : {Cap::kButt, Cap::kSquare, Cap::kRound}) {
231 paint.stroke_cap = cap;
232 canvas.DrawPath(path.Clone(), paint);
233 canvas.Translate({80, 0});
234 }
235 canvas.Translate({-240, 60});
236 }
237
238 return canvas.EndRecordingAsPicture();
239 };
240
241 ASSERT_TRUE(OpenPlaygroundHere(callback));
242 }

References impeller::PathBuilder::AddCircle(), impeller::Color::Black(), impeller::Canvas::ClipPath(), impeller::Path::Clone(), impeller::Close(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::GetCurrentTransform(), impeller::TPoint< T >::GetDistance(), IMPELLER_PLAYGROUND_LINE, 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(), 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() [175/384]

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

Definition at line 2182 of file aiks_unittests.cc.

2182 {
2183 Canvas canvas;
2184
2185 canvas.SaveLayer({
2186 .color_filter = ColorFilter::MakeSrgbToLinear(),
2187 });
2188
2189 canvas.Translate({500, 300, 0});
2190 canvas.Rotate(Radians(2 * kPi / 3));
2191 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
2192
2193 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2194 }

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

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

Definition at line 1306 of file aiks_unittests.cc.

1306 {
1307 Canvas canvas;
1308 canvas.Scale(GetContentScale());
1309 Paint paint;
1310 const int color_count = 3;
1311 Color colors[color_count] = {
1312 Color::Blue(),
1313 Color::Green(),
1314 Color::Crimson(),
1315 };
1316
1317 paint.color = Color::White();
1318 canvas.DrawPaint(paint);
1319
1320 int c_index = 0;
1321
1322 auto draw = [&paint, &colors, &c_index](Canvas& canvas, Point center,
1323 Scalar r, Scalar dr, int n) {
1324 for (int i = 0; i < n; i++) {
1325 paint.color = colors[(c_index++) % color_count];
1326 canvas.DrawCircle(center, r, paint);
1327 r += dr;
1328 }
1329 };
1330
1331 paint.style = Paint::Style::kStroke;
1332 paint.stroke_width = 1;
1333 draw(canvas, {10, 10}, 2, 2, 14); // r = [2, 28], covers [1,29]
1334 paint.stroke_width = 5;
1335 draw(canvas, {10, 10}, 35, 10, 56); // r = [35, 585], covers [30,590]
1336
1337 std::vector<Color> gradient_colors = {
1338 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1339 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1340 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1341 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1342 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1343 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1344 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1345 std::vector<Scalar> stops = {
1346 0.0,
1347 (1.0 / 6.0) * 1,
1348 (1.0 / 6.0) * 2,
1349 (1.0 / 6.0) * 3,
1350 (1.0 / 6.0) * 4,
1351 (1.0 / 6.0) * 5,
1352 1.0,
1353 };
1354 auto texture = CreateTextureForFixture("airplane.jpg",
1355 /*enable_mipmapping=*/true);
1356
1357 paint.color_source = ColorSource::MakeRadialGradient(
1358 {500, 600}, 75, std::move(gradient_colors), std::move(stops),
1359 Entity::TileMode::kMirror, {});
1360 draw(canvas, {500, 600}, 5, 10, 10);
1361
1362 paint.color_source = ColorSource::MakeImage(
1363 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1364 Matrix::MakeTranslation({700, 200}));
1365 draw(canvas, {800, 300}, 5, 10, 10);
1366
1367 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1368 }

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

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

Definition at line 3766 of file aiks_unittests.cc.

3766 {
3767 Canvas canvas;
3768
3769 // Use a non-srcOver blend mode to ensure that we don't detect this as an
3770 // opacity peephole optimization.
3771 canvas.SaveLayer(
3772 {.color = Color::Blue().WithAlpha(0.5), .blend_mode = BlendMode::kSource},
3773 Rect::MakeLTRB(0, 0, 200, 200));
3774 canvas.DrawPaint(
3775 {.color = Color::BlackTransparent(), .blend_mode = BlendMode::kSource});
3776 canvas.Restore();
3777
3778 canvas.SaveLayer(
3779 {.color = Color::Blue(), .blend_mode = BlendMode::kDestinationOver});
3780 canvas.Restore();
3781
3782 // This playground should appear blank on CI since we are only drawing
3783 // transparent black. If the clear color optimization is broken, the texture
3784 // will be filled with NaNs and may produce a magenta texture on macOS or iOS.
3785 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3786 }

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

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

Definition at line 2963 of file aiks_unittests.cc.

2963 {
2964 auto mapping = flutter::testing::OpenFixtureAsSkData("Roboto-Regular.ttf");
2965 ASSERT_NE(mapping, nullptr);
2966
2967 Scalar font_size = 100;
2968 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
2969 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
2970
2971 Paint text_paint;
2972 text_paint.color = Color::Blue();
2973
2974 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
2975 Color{0.1294, 0.5882, 0.9529, 1.0}};
2976 std::vector<Scalar> stops = {
2977 0.0,
2978 1.0,
2979 };
2980 text_paint.color_source = ColorSource::MakeLinearGradient(
2981 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
2982 Entity::TileMode::kRepeat, {});
2983
2984 Canvas canvas;
2985 canvas.Translate({100, 100});
2986 canvas.Rotate(Radians(kPi / 4));
2987
2988 auto blob = SkTextBlob::MakeFromString("Hello", sk_font);
2989 ASSERT_NE(blob, nullptr);
2990 auto frame = MakeTextFrameFromTextBlobSkia(blob);
2991 canvas.DrawTextFrame(frame, Point(), text_paint);
2992
2993 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2994 }

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

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

Definition at line 771 of file aiks_unittests.cc.

771 {
772 std::array<Scalar, 20> phase_offsets;
773 for (Scalar& offset : phase_offsets) {
774 auto rand = std::rand(); // NOLINT
775 offset = (static_cast<float>(rand) / static_cast<float>(RAND_MAX)) * k2Pi;
776 }
777
778 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
779 static float font_size = 20;
780 static float phase_variation = 0.2;
781 static float speed = 0.5;
782 static float magnitude = 100;
783 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
784 ImGui::SliderFloat("Font size", &font_size, 5, 50);
785 ImGui::SliderFloat("Phase variation", &phase_variation, 0, 1);
786 ImGui::SliderFloat("Oscillation speed", &speed, 0, 2);
787 ImGui::SliderFloat("Oscillation magnitude", &magnitude, 0, 300);
788 ImGui::End();
789
790 Canvas canvas;
791 canvas.Scale(GetContentScale());
792
793 for (size_t i = 0; i < phase_offsets.size(); i++) {
794 auto position = Point(
795 200 + magnitude * std::sin((-phase_offsets[i] * phase_variation +
796 GetSecondsElapsed() * speed)), //
797 200 + i * font_size * 1.1 //
798 );
799 if (!RenderTextInCanvasSkia(
800 GetContext(), canvas,
801 "the quick brown fox jumped over "
802 "the lazy dog!.?",
803 "Roboto-Regular.ttf",
804 {.font_size = font_size, .position = position})) {
805 return std::nullopt;
806 }
807 }
808 return canvas.EndRecordingAsPicture();
809 };
810
811 ASSERT_TRUE(OpenPlaygroundHere(callback));
812 }

References impeller::Canvas::EndRecordingAsPicture(), impeller::k2Pi, RenderTextInCanvasSkia(), and impeller::Canvas::Scale().

## ◆ TEST_P() [180/384]

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

Definition at line 923 of file aiks_unittests.cc.

923 {
924 Canvas canvas;
925 canvas.Scale(GetContentScale());
926 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
927
928 canvas.Transform(Matrix(0.25, -0.3, 0, -0.002, //
929 0, 0.5, 0, 0, //
930 0, 0, 0.3, 0, //
931 100, 100, 0, 1.3));
932 ASSERT_TRUE(RenderTextInCanvasSkia(
933 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
934 "Roboto-Regular.ttf"));
935
936 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
937 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), RenderTextInCanvasSkia(), impeller::Canvas::Scale(), and impeller::Canvas::Transform().

## ◆ TEST_P() [181/384]

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

Definition at line 1208 of file aiks_unittests.cc.

1208 {
1209 Canvas canvas;
1210 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(), Matrix());
1211
1212 // clang-format off
1213 canvas.Translate(Vector3(100, 200));
1214 ASSERT_MATRIX_NEAR(
1215 canvas.GetCurrentTransform(),
1216 Matrix( 1, 0, 0, 0,
1217 0, 1, 0, 0,
1218 0, 0, 1, 0,
1219 100, 200, 0, 1));
1220
1221 canvas.Rotate(Radians(kPiOver2));
1222 ASSERT_MATRIX_NEAR(
1223 canvas.GetCurrentTransform(),
1224 Matrix( 0, 1, 0, 0,
1225 -1, 0, 0, 0,
1226 0, 0, 1, 0,
1227 100, 200, 0, 1));
1228
1229 canvas.Scale(Vector3(2, 3));
1230 ASSERT_MATRIX_NEAR(
1231 canvas.GetCurrentTransform(),
1232 Matrix( 0, 2, 0, 0,
1233 -3, 0, 0, 0,
1234 0, 0, 0, 0,
1235 100, 200, 0, 1));
1236
1237 canvas.Translate(Vector3(100, 200));
1238 ASSERT_MATRIX_NEAR(
1239 canvas.GetCurrentTransform(),
1240 Matrix( 0, 2, 0, 0,
1241 -3, 0, 0, 0,
1242 0, 0, 0, 0,
1243 -500, 400, 0, 1));
1244 // clang-format on
1245 }

References ASSERT_MATRIX_NEAR, impeller::Canvas::GetCurrentTransform(), impeller::kPiOver2, impeller::Canvas::Rotate(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [182/384]

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

Definition at line 2288 of file aiks_unittests.cc.

2288 {
2289 Canvas canvas;
2290
2291 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
2292
2293 canvas.SaveLayer({.color = Color::Black().WithAlpha(0.5)});
2294 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
2295 canvas.Restore();
2296
2297 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2298 }

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

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

Definition at line 2461 of file aiks_unittests.cc.

2461 {
2462 Canvas canvas;
2463
2464 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2465 canvas.DrawImage(image, {100, 100}, {});
2466
2467 canvas.SaveLayer({.color = Color::Black().WithAlpha(0.5)});
2468 canvas.DrawImage(image, {100, 500}, {});
2469 canvas.Restore();
2470
2471 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2472 }

References impeller::Color::Black(), impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [184/384]

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

Definition at line 2545 of file aiks_unittests.cc.

2545 {
2546 Canvas canvas;
2547 canvas.DrawRect(Rect::MakeXYWH(0, 0, 400, 400), {.color = Color::Red()});
2548 canvas.SaveLayer({
2549 .color = Color::Black().WithAlpha(0.5),
2550 .blend_mode = BlendMode::kLighten,
2551 });
2552 canvas.DrawCircle({200, 200}, 100, {.color = Color::Green()});
2553 canvas.Restore();
2554 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2555 }

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

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

Definition at line 2300 of file aiks_unittests.cc.

2300 {
2301 Canvas canvas;
2302
2303 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
2304
2305 canvas.SaveLayer({
2306 .color = Color::Black().WithAlpha(0.5),
2307 .color_filter =
2308 ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red()),
2309 });
2310 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
2311 canvas.Restore();
2312
2313 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2314 }

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

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

Definition at line 2316 of file aiks_unittests.cc.

2316 {
2317 Canvas canvas;
2318
2319 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
2320
2321 canvas.SaveLayer({
2322 .color = Color::Black().WithAlpha(0.5),
2323 .image_filter = ImageFilter::MakeFromColorFilter(
2324 *ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red())),
2325 });
2326
2327 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
2328 canvas.Restore();
2329
2330 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2331 }

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

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

Definition at line 2333 of file aiks_unittests.cc.

2333 {
2334 Canvas canvas;
2335
2336 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
2337
2338 canvas.SaveLayer({
2339 .color = Color::Black().WithAlpha(0.5),
2340 .color_filter =
2341 ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red()),
2342 });
2343
2344 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
2345 canvas.Restore();
2346
2347 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2348 }

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

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

Definition at line 2519 of file aiks_unittests.cc.

2520 {
2521 Canvas canvas;
2522
2523 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2524 canvas.DrawImage(image, {100, 100}, {});
2525
2526 canvas.SaveLayer({
2527 .color = Color::Black().WithAlpha(0.5),
2528 .image_filter = ImageFilter::MakeFromColorFilter(
2529 *ColorFilter::MakeMatrix({.array =
2530 {
2531 1, 0, 0, 0, 0, //
2532 0, 1, 0, 0, 0, //
2533 0, 0.2, 1, 0, 0, //
2534 0, 0, 0, 0.5, 0 //
2535 }})),
2536 .color_filter =
2537 ColorFilter::MakeBlend(BlendMode::kModulate, Color::Green()),
2538 });
2539 canvas.DrawImage(image, {100, 500}, {});
2540 canvas.Restore();
2541
2542 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2543 }

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

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

Definition at line 2474 of file aiks_unittests.cc.

2474 {
2475 Canvas canvas;
2476
2477 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2478 canvas.DrawImage(image, {100, 100}, {});
2479
2480 canvas.SaveLayer({
2481 .color = Color::Black().WithAlpha(0.5),
2482 .color_filter = ColorFilter::MakeMatrix({.array =
2483 {
2484 1, 0, 0, 0, 0, //
2485 0, 1, 0, 0, 0, //
2486 0, 0, 1, 0, 0, //
2487 0, 0, 0, 2, 0 //
2488 }}),
2489 });
2490 canvas.DrawImage(image, {100, 500}, {});
2491 canvas.Restore();
2492
2493 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2494 }

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

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

Definition at line 2496 of file aiks_unittests.cc.

2496 {
2497 Canvas canvas;
2498
2499 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2500 canvas.DrawImage(image, {100, 100}, {});
2501
2502 canvas.SaveLayer({
2503 .color = Color::Black().WithAlpha(0.5),
2504 .image_filter = ImageFilter::MakeFromColorFilter(
2505 *ColorFilter::MakeMatrix({.array =
2506 {
2507 1, 0, 0, 0, 0, //
2508 0, 1, 0, 0, 0, //
2509 0, 0, 1, 0, 0, //
2510 0, 0, 0, 2, 0 //
2511 }})),
2512 });
2513 canvas.DrawImage(image, {100, 500}, {});
2514 canvas.Restore();
2515
2516 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2517 }

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

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

Definition at line 3312 of file aiks_unittests.cc.

3312 {
3313 Canvas canvas;
3314 Paint paint;
3315 auto texture = CreateTextureForFixture("table_mountain_nx.png");
3316
3317 paint.color_source = ColorSource::MakeImage(texture, Entity::TileMode::kClamp,
3318 Entity::TileMode::kClamp, {}, {});
3319
3320 auto vertices = {Point(0, 0), Point(texture->GetSize().width, 0),
3321 Point(0, texture->GetSize().height)};
3322 std::vector<uint16_t> indices = {0u, 1u, 2u};
3323 std::vector<Point> texture_coordinates = {};
3324 std::vector<Color> vertex_colors = {};
3325 auto geometry = std::make_shared<VerticesGeometry>(
3326 vertices, indices, texture_coordinates, vertex_colors,
3327 Rect::MakeLTRB(0, 0, 1, 1), VerticesGeometry::VertexMode::kTriangleStrip);
3328
3329 canvas.DrawVertices(geometry, BlendMode::kSourceOver, paint);
3330 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3331 }

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

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

Definition at line 3334 of file aiks_unittests.cc.

3334 {
3335 Canvas canvas;
3336 Paint paint;
3337 auto texture = CreateTextureForFixture("table_mountain_nx.png");
3338
3339 paint.color_source = ColorSource::MakeImage(
3340 texture, Entity::TileMode::kClamp, Entity::TileMode::kClamp, {},
3341 Matrix::MakeTranslation({100.0, 100.0}));
3342
3343 auto vertices = {Point(0, 0), Point(texture->GetSize().width, 0),
3344 Point(0, texture->GetSize().height)};
3345 std::vector<uint16_t> indices = {0u, 1u, 2u};
3346 std::vector<Point> texture_coordinates = {};
3347 std::vector<Color> vertex_colors = {};
3348 auto geometry = std::make_shared<VerticesGeometry>(
3349 vertices, indices, texture_coordinates, vertex_colors,
3350 Rect::MakeLTRB(0, 0, 1, 1), VerticesGeometry::VertexMode::kTriangleStrip);
3351
3352 canvas.DrawVertices(geometry, BlendMode::kSourceOver, paint);
3353 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3354 }

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

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 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
28
29 TextureDescriptor dst_format;
30 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
31 dst_format.size = {100, 100};
32 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
33
34 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
35 }

References impeller::TextureDescriptor::format, impeller::kA8UNormInt, impeller::kR8G8B8A8UNormInt, and impeller::TextureDescriptor::size.

## ◆ TEST_P() [194/384]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitAcrossDifferentSampleCountsFails |
| ) |  |

Definition at line 37 of file blit_pass_unittests.cc.

37 {
38 ScopedValidationDisable scope; // avoid noise in output.
39 auto context = GetContext();
40 auto cmd_buffer = context->CreateCommandBuffer();
41 auto blit_pass = cmd_buffer->CreateBlitPass();
42
43 TextureDescriptor src_desc;
44 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
45 src_desc.sample_count = SampleCount::kCount4;
46 src_desc.size = {100, 100};
47 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
48
49 TextureDescriptor dst_format;
50 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
51 dst_format.size = {100, 100};
52 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
53
54 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
55 }

References impeller::TextureDescriptor::format, impeller::kCount4, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::sample_count, and impeller::TextureDescriptor::size.

## ◆ TEST_P() [195/384]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitPassesForMatchingFormats |
| ) |  |

Definition at line 57 of file blit_pass_unittests.cc.

57 {
58 ScopedValidationDisable scope; // avoid noise in output.
59 auto context = GetContext();
60 auto cmd_buffer = context->CreateCommandBuffer();
61 auto blit_pass = cmd_buffer->CreateBlitPass();
62
63 TextureDescriptor src_desc;
64 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
65 src_desc.size = {100, 100};
66 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
67
68 TextureDescriptor dst_format;
69 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
70 dst_format.size = {100, 100};
71 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
72
73 EXPECT_TRUE(blit_pass->AddCopy(src, dst));
74 }

References impeller::TextureDescriptor::format, impeller::kR8G8B8A8UNormInt, and impeller::TextureDescriptor::size.

## ◆ TEST_P() [196/384]

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

impeller::testing::TEST_P | ( | ComputeSubgroupTest | ,
|  | LargePath |
| ) |  |

Definition at line 177 of file compute_subgroup_unittests.cc.

177 {
178 // The path in here is large enough to highlight issues around exceeding
179 // subgroup size.
180 using SS = StrokeComputeShader;
181
182 auto context = GetContext();
183 ASSERT_TRUE(context);
184 ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
185 size_t vertex_count = 0;
186 Scalar stroke_width = 1.0;
187
188 auto vertex_buffer = CreateHostVisibleDeviceBuffer<SS::VertexBuffer<2048>>(
189 context, "VertexBuffer");
190 auto vertex_buffer_count =
191 CreateHostVisibleDeviceBuffer<SS::VertexBufferCount>(context,
192 "VertexCount");
193
194 auto complex_path =
195 PathBuilder{}
196 .MoveTo({359.934, 96.6335})
197 .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
198 {354.673, 96.8895})
199 .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
200 {354.367, 96.9075})
201 .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
202 {349.259, 97.2355})
203 .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
204 {348.625, 97.2834})
205 .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
206 {343.789, 97.6722})
207 .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
208 {342.703, 97.7734})
209 .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
210 {338.246, 98.207})
211 .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
212 {336.612, 98.3894})
213 .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
214 {332.623, 98.8476})
215 .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
216 {332.237, 98.8982})
217 .LineTo({332.237, 102.601})
218 .LineTo({321.778, 102.601})
219 .LineTo({321.778, 100.382})
220 .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
221 {321.161, 100.476})
222 .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
223 {315.332, 101.479})
224 .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
225 {315.301, 101.484})
226 .LineTo({310.017, 105.94})
227 .LineTo({309.779, 105.427})
228 .LineTo({314.403, 101.651})
229 .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
230 {314.368, 101.658})
231 .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
232 {308.846, 102.748})
233 .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
234 .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
235 {303.425, 103.936})
236 .LineTo({299.105, 107.578})
237 .LineTo({298.867, 107.065})
238 .LineTo({302.394, 104.185})
239 .LineTo({302.412, 104.171})
240 .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
241 {299.344, 104.921})
242 .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
243 .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
244 {291.462, 106.979})
245 .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
246 {290.471, 107.257})
247 .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
248 {287.449, 108.139})
249 .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
250 {284.536, 109.035})
251 .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
252 {281.952, 109.859})
253 .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
254 {279.633, 110.638})
255 .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
256 {276.803, 111.607})
257 .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
258 {276.672, 111.653})
259 .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
260 {271.721, 113.463})
261 .LineTo({271.717, 113.449})
262 .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
263 {270.963, 113.628})
264 .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
265 {270.748, 113.682})
266 .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
267 {269.839, 113.926})
268 .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
269 {269.681, 113.972})
270 .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
271 {268.756, 114.239})
272 .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
273 {268.367, 114.354})
274 .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
275 {267.752, 114.54})
276 .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
277 {253.564, 119.252})
278 .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
279 {253.538, 119.261})
280 .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
281 {248.189, 121.131})
282 .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
283 .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
284 {245.975, 121.912})
285 .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
286 {244.698, 122.364})
287 .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
288 {242.794, 123.04})
289 .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
290 {240.961, 123.693})
291 .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
292 {240.052, 124.018})
293 .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
294 .LineTo({237.164, 125.003})
295 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
296 {235.81, 125.538})
297 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
298 {234.592, 125.977})
299 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
300 {234.59, 125.977})
301 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
302 {192.381, 141.429})
303 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
304 .LineTo({360, 160})
305 .LineTo({360, 119.256})
306 .LineTo({360, 106.332})
307 .LineTo({360, 96.6307})
308 .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
309 {359.934, 96.6335})
310 .Close()
311 .TakePath();
312
313 auto callback = [&](RenderPass& pass) -> bool {
314 ::memset(vertex_buffer_count->AsBufferView().contents, 0,
315 sizeof(SS::VertexBufferCount));
316 ::memset(vertex_buffer->AsBufferView().contents, 0,
317 sizeof(SS::VertexBuffer<2048>));
318
319 ComputeTessellator{}
320 .SetStrokeWidth(stroke_width)
321 .Tessellate(
322 complex_path, context, vertex_buffer->AsBufferView(),
323 vertex_buffer_count->AsBufferView(),
324 [vertex_buffer_count, &vertex_count](CommandBuffer::Status status) {
325 vertex_count = reinterpret_cast<SS::VertexBufferCount*>(
326 vertex_buffer_count->AsBufferView().contents)
327 ->count;
328 });
329
330 ContentContext renderer(context, nullptr);
331 if (!renderer.IsValid()) {
332 return false;
333 }
334
335 using VS = SolidFillPipeline::VertexShader;
336
337 Command cmd;
338 DEBUG_COMMAND_INFO(cmd, "Draw Stroke");
339 cmd.stencil_reference = 0;
340
341 ContentContextOptions options;
342 options.sample_count = pass.GetRenderTarget().GetSampleCount();
343 options.color_attachment_pixel_format =
344 pass.GetRenderTarget().GetRenderTargetPixelFormat();
345 options.has_stencil_attachment =
346 pass.GetRenderTarget().GetStencilAttachment().has_value();
347 options.blend_mode = BlendMode::kSourceIn;
348 options.primitive_type = PrimitiveType::kTriangleStrip;
349 options.stencil_compare = CompareFunction::kEqual;
350 options.stencil_operation = StencilOperation::kIncrementClamp;
351
352 cmd.pipeline = renderer.GetSolidFillPipeline(options);
353
354 auto count = reinterpret_cast<SS::VertexBufferCount*>(
355 vertex_buffer_count->AsBufferView().contents)
356 ->count;
357
358 cmd.BindVertices(
359 VertexBuffer{.vertex_buffer = vertex_buffer->AsBufferView(),
360 .vertex_count = count,
361 .index_type = IndexType::kNone});
362
363 VS::FrameInfo frame_info;
364 auto world_matrix = Matrix::MakeScale(GetContentScale());
365 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
366 frame_info.color = Color::Red().Premultiply();
367 VS::BindFrameInfo(cmd,
368 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
369
370 if (!pass.AddCommand(std::move(cmd))) {
371 return false;
372 }
373
374 return true;
375 };
376 ASSERT_TRUE(OpenPlaygroundHere(callback));
377 }

References impeller::Command::BindVertices(), impeller::ContentContextOptions::blend_mode, impeller::Close(), impeller::ContentContextOptions::color_attachment_pixel_format, DEBUG_COMMAND_INFO, impeller::ContentContext::GetSolidFillPipeline(), impeller::ContentContextOptions::has_stencil_attachment, impeller::ContentContext::IsValid(), impeller::kEqual, impeller::kIncrementClamp, impeller::kNone, impeller::kSourceIn, impeller::kTriangleStrip, impeller::LineTo(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Command::pipeline, impeller::Color::Premultiply(), impeller::ContentContextOptions::primitive_type, impeller::Color::Red(), impeller::ContentContextOptions::sample_count, impeller::ComputeTessellator::SetStrokeWidth(), impeller::ContentContextOptions::stencil_compare, impeller::ContentContextOptions::stencil_operation, impeller::Command::stencil_reference, impeller::ComputeTessellator::Tessellate(), and impeller::VertexBuffer::vertex_buffer.

## ◆ TEST_P() [198/384]

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->AsBufferView().contents, 0,
74 sizeof(SS::VertexBufferCount));
75 ::memset(vertex_buffer->AsBufferView().contents, 0,
76 sizeof(SS::VertexBuffer<2048>));
77 const auto* main_viewport = ImGui::GetMainViewport();
78 ImGui::SetNextWindowPos(
79 ImVec2(main_viewport->WorkPos.x + 650, main_viewport->WorkPos.y + 20));
80 ImGui::Begin("Path data", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
81 ImGui::InputTextMultiline("Path", svg_path_data,
82 IM_ARRAYSIZE(svg_path_data));
83 ImGui::DragFloat("Stroke width", &stroke_width, .1, 0.0, 25.0);
84
85 SkPath sk_path;
86 if (SkParsePath::FromSVGString(svg_path_data, &sk_path)) {
87 std::promise<bool> promise;
88 auto future = promise.get_future();
89
90 auto path = skia_conversions::ToPath(sk_path);
91 auto status =
92 ComputeTessellator{}
93 .SetStrokeWidth(stroke_width)
94 .Tessellate(
95 path, context, vertex_buffer->AsBufferView(),
96 vertex_buffer_count->AsBufferView(),
97 [vertex_buffer_count, &vertex_count,
98 &promise](CommandBuffer::Status status) {
99 vertex_count =
100 reinterpret_cast<SS::VertexBufferCount*>(
101 vertex_buffer_count->AsBufferView().contents)
102 ->count;
103 promise.set_value(status ==
104 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 Command cmd;
136 DEBUG_COMMAND_INFO(cmd, "Draw Stroke");
137 cmd.stencil_reference = 0;
138
139 ContentContextOptions options;
140 options.sample_count = pass.GetRenderTarget().GetSampleCount();
141 options.color_attachment_pixel_format =
142 pass.GetRenderTarget().GetRenderTargetPixelFormat();
143 options.has_stencil_attachment =
144 pass.GetRenderTarget().GetStencilAttachment().has_value();
145 options.blend_mode = BlendMode::kSourceIn;
146 options.primitive_type = PrimitiveType::kTriangleStrip;
147 options.stencil_compare = CompareFunction::kEqual;
148 options.stencil_operation = StencilOperation::kIncrementClamp;
149
150 cmd.pipeline = renderer.GetSolidFillPipeline(options);
151
152 auto count = reinterpret_cast<SS::VertexBufferCount*>(
153 vertex_buffer_count->AsBufferView().contents)
154 ->count;
155
156 cmd.BindVertices(
157 VertexBuffer{.vertex_buffer = vertex_buffer->AsBufferView(),
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(cmd,
166 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
167
168 if (!pass.AddCommand(std::move(cmd))) {
169 return false;
170 }
171
172 return true;
173 };
174 ASSERT_TRUE(OpenPlaygroundHere(callback));
175 }

References impeller::Command::BindVertices(), impeller::ContentContextOptions::blend_mode, impeller::ContentContextOptions::color_attachment_pixel_format, DEBUG_COMMAND_INFO, impeller::ContentContext::GetSolidFillPipeline(), impeller::ContentContextOptions::has_stencil_attachment, impeller::ContentContext::IsValid(), impeller::ComputeTessellator::kCommandInvalid, impeller::kEqual, impeller::kIncrementClamp, impeller::kNone, impeller::ComputeTessellator::kOk, impeller::kSourceIn, impeller::ComputeTessellator::kTooManyComponents, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), impeller::Command::pipeline, impeller::Color::Premultiply(), impeller::ContentContextOptions::primitive_type, impeller::Color::Red(), impeller::ContentContextOptions::sample_count, impeller::ComputeTessellator::SetStrokeWidth(), impeller::ContentContextOptions::stencil_compare, impeller::ContentContextOptions::stencil_operation, impeller::Command::stencil_reference, impeller::ComputeTessellator::Tessellate(), impeller::skia_conversions::ToPath(), and impeller::VertexBuffer::vertex_buffer.

## ◆ TEST_P() [199/384]

impeller::testing::TEST_P | ( | ComputeSubgroupTest | ,
|  | QuadAndCubicInOnePath |
| ) |  |

Definition at line 379 of file compute_subgroup_unittests.cc.

379 {
380 using SS = StrokeComputeShader;
381
382 auto context = GetContext();
383 ASSERT_TRUE(context);
384 ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
385
386 auto vertex_buffer = CreateHostVisibleDeviceBuffer<SS::VertexBuffer<2048>>(
387 context, "VertexBuffer");
388 auto vertex_buffer_count =
389 CreateHostVisibleDeviceBuffer<SS::VertexBufferCount>(context,
390 "VertexBufferCount");
391
392 auto path = PathBuilder{}
393 .AddCubicCurve({140, 20}, {73, 20}, {20, 74}, {20, 140})
394 .AddQuadraticCurve({20, 140}, {93, 90}, {100, 42})
395 .TakePath();
396
397 auto tessellator = ComputeTessellator{};
398
399 fml::AutoResetWaitableEvent latch;
400
401 auto status = tessellator.Tessellate(
402 path, context, vertex_buffer->AsBufferView(),
403 vertex_buffer_count->AsBufferView(),
404 [&latch](CommandBuffer::Status status) {
405 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
406 latch.Signal();
407 });
408
409 ASSERT_EQ(status, ComputeTessellator::Status::kOk);
410
411 auto callback = [&](RenderPass& pass) -> bool {
412 ContentContext renderer(context, nullptr);
413 if (!renderer.IsValid()) {
414 return false;
415 }
416
417 using VS = SolidFillPipeline::VertexShader;
418
419 Command cmd;
420 DEBUG_COMMAND_INFO(cmd, "Draw Stroke");
421 cmd.stencil_reference = 0;
422
423 ContentContextOptions options;
424 options.sample_count = pass.GetRenderTarget().GetSampleCount();
425 options.color_attachment_pixel_format =
426 pass.GetRenderTarget().GetRenderTargetPixelFormat();
427 options.has_stencil_attachment =
428 pass.GetRenderTarget().GetStencilAttachment().has_value();
429 options.blend_mode = BlendMode::kSourceIn;
430 options.primitive_type = PrimitiveType::kTriangleStrip;
431 options.stencil_compare = CompareFunction::kEqual;
432 options.stencil_operation = StencilOperation::kIncrementClamp;
433
434 cmd.pipeline = renderer.GetSolidFillPipeline(options);
435
436 auto count = reinterpret_cast<SS::VertexBufferCount*>(
437 vertex_buffer_count->AsBufferView().contents)
438 ->count;
439
440 cmd.BindVertices(
441 VertexBuffer{.vertex_buffer = vertex_buffer->AsBufferView(),
442 .vertex_count = count,
443 .index_type = IndexType::kNone});
444
445 VS::FrameInfo frame_info;
446 auto world_matrix = Matrix::MakeScale(GetContentScale());
447 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
448 frame_info.color = Color::Red().Premultiply();
449 VS::BindFrameInfo(cmd,
450 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
451
452 if (!pass.AddCommand(std::move(cmd))) {
453 return false;
454 }
455
456 return true;
457 };
458 ASSERT_TRUE(OpenPlaygroundHere(callback));
459
460 // The latch is down here because it's expected that on Metal the backend
461 // will take care of synchronizing the buffer between the compute and render
462 // pass usages, since it's not MTLHeap allocated. However, if playgrounds
463 // are disabled, no render pass actually gets submitted and we need to do a
464 // CPU latch here.
465 latch.Wait();
466
467 auto vertex_count = reinterpret_cast<SS::VertexBufferCount*>(
468 vertex_buffer_count->AsBufferView().contents)
469 ->count;
470 EXPECT_EQ(vertex_count, golden_cubic_and_quad_points.size());
471 auto vertex_buffer_data = reinterpret_cast<SS::VertexBuffer<2048>*>(
472 vertex_buffer->AsBufferView().contents);
473 for (size_t i = 0; i < vertex_count; i++) {
474 EXPECT_LT(std::abs(golden_cubic_and_quad_points[i].x -
475 vertex_buffer_data->position[i].x),
476 1e-3);
477 EXPECT_LT(std::abs(golden_cubic_and_quad_points[i].y -
478 vertex_buffer_data->position[i].y),
479 1e-3);
480 }
481 }

References impeller::PathBuilder::AddCubicCurve(), impeller::Command::BindVertices(), impeller::ContentContextOptions::blend_mode, impeller::ContentContextOptions::color_attachment_pixel_format, DEBUG_COMMAND_INFO, impeller::ContentContext::GetSolidFillPipeline(), golden_cubic_and_quad_points, impeller::ContentContextOptions::has_stencil_attachment, impeller::ContentContext::IsValid(), impeller::kEqual, impeller::kIncrementClamp, impeller::kNone, impeller::ComputeTessellator::kOk, impeller::kSourceIn, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), impeller::Command::pipeline, impeller::Color::Premultiply(), impeller::ContentContextOptions::primitive_type, impeller::Color::Red(), impeller::ContentContextOptions::sample_count, impeller::ContentContextOptions::stencil_compare, impeller::ContentContextOptions::stencil_operation, impeller::Command::stencil_reference, impeller::ComputeTessellator::Tessellate(), and impeller::VertexBuffer::vertex_buffer.

## ◆ TEST_P() [200/384]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | 1DThreadgroupSizingIsCorrect |
| ) |  |

Definition at line 178 of file compute_unittests.cc.

178 {
179 using CS = ThreadgroupSizingTestComputeShader;
180 auto context = GetContext();
181 ASSERT_TRUE(context);
182 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
183
184 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
185 auto pipeline_desc =
186 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
187 ASSERT_TRUE(pipeline_desc.has_value());
188 auto compute_pipeline =
189 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
190 ASSERT_TRUE(compute_pipeline);
191
192 auto cmd_buffer = context->CreateCommandBuffer();
193 auto pass = cmd_buffer->CreateComputePass();
194 ASSERT_TRUE(pass && pass->IsValid());
195
196 static constexpr size_t kCount = 2048;
197
198 pass->SetGridSize(ISize(kCount, 1));
199 pass->SetThreadGroupSize(ISize(kCount, 1));
200
201 ComputeCommand cmd;
202 cmd.pipeline = compute_pipeline;
203
204 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
205 context, "Output Buffer");
206
207 CS::BindOutputData(cmd, output_buffer->AsBufferView());
208
209 ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
210 ASSERT_TRUE(pass->EncodeCommands());
211
212 fml::AutoResetWaitableEvent latch;
213 ASSERT_TRUE(cmd_buffer->SubmitCommands(
214 [&latch, output_buffer](CommandBuffer::Status status) {
215 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
216
217 auto view = output_buffer->AsBufferView();
218 EXPECT_EQ(view.range.length, sizeof(CS::OutputData<kCount>));
219
220 CS::OutputData<kCount>* output =
221 reinterpret_cast<CS::OutputData<kCount>*>(view.contents);
222 EXPECT_TRUE(output);
223 EXPECT_EQ(output->data[kCount - 1], kCount - 1);
224 latch.Signal();
225 }));
226
227 latch.Wait();
228 }

References impeller::ComputeCommand::pipeline.

## ◆ TEST_P() [201/384]

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 ASSERT_TRUE(context);
377 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
378
379 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
380 auto pipeline_desc =
381 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
382 ASSERT_TRUE(pipeline_desc.has_value());
383 auto compute_pipeline =
384 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
385 ASSERT_TRUE(compute_pipeline);
386
387 auto cmd_buffer = context->CreateCommandBuffer();
388 auto pass = cmd_buffer->CreateComputePass();
389 ASSERT_TRUE(pass && pass->IsValid());
390
391 static constexpr size_t kCount = 5;
392
393 pass->SetGridSize(ISize(kCount, 1));
394
395 ComputeCommand cmd;
396 cmd.pipeline = compute_pipeline;
397
398 CS::Info info{.count = kCount};
399 CS::Input0<kCount> input_0;
400 CS::Input1<kCount> input_1;
401 for (size_t i = 0; i < kCount; i++) {
402 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
403 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
404 }
405
406 input_0.fixed_array[1] = IPoint32(2, 2);
407 input_1.fixed_array[0] = UintPoint32(3, 3);
408 input_0.some_int = 5;
409 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
410
411 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
412 context, "Output Buffer");
413
414 CS::BindInfo(cmd, pass->GetTransientsBuffer().EmplaceUniform(info));
415 CS::BindInput0(cmd,
416 pass->GetTransientsBuffer().EmplaceStorageBuffer(input_0));
417 CS::BindInput1(cmd,
418 pass->GetTransientsBuffer().EmplaceStorageBuffer(input_1));
419 CS::BindOutput(cmd, output_buffer->AsBufferView());
420
421 ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
422 ASSERT_TRUE(pass->EncodeCommands());
423
424 fml::AutoResetWaitableEvent latch;
425 ASSERT_TRUE(
426 cmd_buffer->SubmitCommands([&latch, output_buffer, &input_0,
427 &input_1](CommandBuffer::Status status) {
428 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
429
430 auto view = output_buffer->AsBufferView();
431 EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
432
433 CS::Output<kCount>* output =
434 reinterpret_cast<CS::Output<kCount>*>(view.contents);
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, Vector4(computed.x + 2 + input_1.some_struct.i,
440 computed.y + 3 + input_1.some_struct.vf.x,
441 computed.z + 5 + input_1.some_struct.vf.y,
442 computed.w));
443 }
444 latch.Signal();
445 }));
446
447 latch.Wait();
448 }

References impeller::ComputeCommand::pipeline.

## ◆ TEST_P() [202/384]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanComputePrefixSum |
| ) |  |

Definition at line 113 of file compute_unittests.cc.

113 {
114 using CS = PrefixSumTestComputeShader;
115 auto context = GetContext();
116 ASSERT_TRUE(context);
117 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
118
119 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
120 auto pipeline_desc =
121 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
122 ASSERT_TRUE(pipeline_desc.has_value());
123 auto compute_pipeline =
124 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
125 ASSERT_TRUE(compute_pipeline);
126
127 auto cmd_buffer = context->CreateCommandBuffer();
128 auto pass = cmd_buffer->CreateComputePass();
129 ASSERT_TRUE(pass && pass->IsValid());
130
131 static constexpr size_t kCount = 5;
132
133 pass->SetGridSize(ISize(kCount, 1));
134 pass->SetThreadGroupSize(ISize(kCount, 1));
135
136 ComputeCommand cmd;
137 cmd.pipeline = compute_pipeline;
138
139 CS::InputData<kCount> input_data;
140 input_data.count = kCount;
141 for (size_t i = 0; i < kCount; i++) {
142 input_data.data[i] = 1 + i;
143 }
144
145 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
146 context, "Output Buffer");
147
148 CS::BindInputData(
149 cmd, pass->GetTransientsBuffer().EmplaceStorageBuffer(input_data));
150 CS::BindOutputData(cmd, output_buffer->AsBufferView());
151
152 ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
153 ASSERT_TRUE(pass->EncodeCommands());
154
155 fml::AutoResetWaitableEvent latch;
156 ASSERT_TRUE(cmd_buffer->SubmitCommands(
157 [&latch, output_buffer](CommandBuffer::Status status) {
158 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
159
160 auto view = output_buffer->AsBufferView();
161 EXPECT_EQ(view.range.length, sizeof(CS::OutputData<kCount>));
162
163 CS::OutputData<kCount>* output =
164 reinterpret_cast<CS::OutputData<kCount>*>(view.contents);
165 EXPECT_TRUE(output);
166
167 constexpr uint32_t expected[kCount] = {1, 3, 6, 10, 15};
168 for (size_t i = 0; i < kCount; i++) {
169 auto computed_sum = output->data[i];
170 EXPECT_EQ(computed_sum, expected[i]);
171 }
172 latch.Signal();
173 }));
174
175 latch.Wait();
176 }

References impeller::ComputeCommand::pipeline.

## ◆ TEST_P() [203/384]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanComputePrefixSumLargeInteractive |
| ) |  |

Definition at line 230 of file compute_unittests.cc.

230 {
231 using CS = PrefixSumTestComputeShader;
232
233 auto context = GetContext();
234 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->SetGridSize(ISize(kCount, 1));
250
251 ComputeCommand cmd;
252 cmd.pipeline = compute_pipeline;
253
254 CS::InputData<kCount> input_data;
255 input_data.count = kCount;
256 for (size_t i = 0; i < kCount; i++) {
257 input_data.data[i] = 1 + i;
258 }
259
260 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
261 context, "Output Buffer");
262
263 CS::BindInputData(
264 cmd, pass->GetTransientsBuffer().EmplaceStorageBuffer(input_data));
265 CS::BindOutputData(cmd, output_buffer->AsBufferView());
266
267 pass->AddCommand(std::move(cmd));
268 pass->EncodeCommands();
269 return cmd_buffer->SubmitCommands();
270 };
271 ASSERT_TRUE(OpenPlaygroundHere(callback));
272 }

References impeller::ComputeCommand::pipeline.

## ◆ TEST_P() [204/384]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanCreateComputePass |
| ) |  |

Definition at line 35 of file compute_unittests.cc.

35 {
36 using CS = SampleComputeShader;
37 auto context = GetContext();
38 ASSERT_TRUE(context);
39 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
40
41 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
42 auto pipeline_desc =
43 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
44 ASSERT_TRUE(pipeline_desc.has_value());
45 auto compute_pipeline =
46 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
47 ASSERT_TRUE(compute_pipeline);
48
49 auto cmd_buffer = context->CreateCommandBuffer();
50 auto pass = cmd_buffer->CreateComputePass();
51 ASSERT_TRUE(pass && pass->IsValid());
52
53 static constexpr size_t kCount = 5;
54
55 pass->SetGridSize(ISize(kCount, 1));
56 pass->SetThreadGroupSize(ISize(kCount, 1));
57
58 ComputeCommand cmd;
59 cmd.pipeline = compute_pipeline;
60
61 CS::Info info{.count = kCount};
62 CS::Input0<kCount> input_0;
63 CS::Input1<kCount> input_1;
64 for (size_t i = 0; i < kCount; i++) {
65 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
66 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
67 }
68
69 input_0.fixed_array[1] = IPoint32(2, 2);
70 input_1.fixed_array[0] = UintPoint32(3, 3);
71 input_0.some_int = 5;
72 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
73
74 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
75 context, "Output Buffer");
76
77 CS::BindInfo(cmd, pass->GetTransientsBuffer().EmplaceUniform(info));
78 CS::BindInput0(cmd,
79 pass->GetTransientsBuffer().EmplaceStorageBuffer(input_0));
80 CS::BindInput1(cmd,
81 pass->GetTransientsBuffer().EmplaceStorageBuffer(input_1));
82 CS::BindOutput(cmd, output_buffer->AsBufferView());
83
84 ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
85 ASSERT_TRUE(pass->EncodeCommands());
86
87 fml::AutoResetWaitableEvent latch;
88 ASSERT_TRUE(
89 cmd_buffer->SubmitCommands([&latch, output_buffer, &input_0,
90 &input_1](CommandBuffer::Status status) {
91 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
92
93 auto view = output_buffer->AsBufferView();
94 EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
95
96 CS::Output<kCount>* output =
97 reinterpret_cast<CS::Output<kCount>*>(view.contents);
98 EXPECT_TRUE(output);
99 for (size_t i = 0; i < kCount; i++) {
100 Vector4 vector = output->elements[i];
101 Vector4 computed = input_0.elements[i] * input_1.elements[i];
102 EXPECT_EQ(vector, Vector4(computed.x + 2 + input_1.some_struct.i,
103 computed.y + 3 + input_1.some_struct.vf.x,
104 computed.z + 5 + input_1.some_struct.vf.y,
105 computed.w));
106 }
107 latch.Signal();
108 }));
109
110 latch.Wait();
111 }

References impeller::ComputeCommand::pipeline.

## ◆ TEST_P() [205/384]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CapabilitiesReportSupport |
| ) |  |

Definition at line 29 of file compute_unittests.cc.

29 {
30 auto context = GetContext();
31 ASSERT_TRUE(context);
32 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
33 }

## ◆ TEST_P() [206/384]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | MultiStageInputAndOutput |
| ) |  |

Definition at line 274 of file compute_unittests.cc.

274 {
275 using CS1 = Stage1ComputeShader;
276 using Stage1PipelineBuilder = ComputePipelineBuilder<CS1>;
277 using CS2 = Stage2ComputeShader;
278 using Stage2PipelineBuilder = ComputePipelineBuilder<CS2>;
279
280 auto context = GetContext();
281 ASSERT_TRUE(context);
282 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
283
284 auto pipeline_desc_1 =
285 Stage1PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
286 ASSERT_TRUE(pipeline_desc_1.has_value());
287 auto compute_pipeline_1 =
288 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_1).Get();
289 ASSERT_TRUE(compute_pipeline_1);
290
291 auto pipeline_desc_2 =
292 Stage2PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
293 ASSERT_TRUE(pipeline_desc_2.has_value());
294 auto compute_pipeline_2 =
295 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_2).Get();
296 ASSERT_TRUE(compute_pipeline_2);
297
298 auto cmd_buffer = context->CreateCommandBuffer();
299 auto pass = cmd_buffer->CreateComputePass();
300 ASSERT_TRUE(pass && pass->IsValid());
301
302 static constexpr size_t kCount1 = 5;
303 static constexpr size_t kCount2 = kCount1 * 2;
304
305 pass->SetGridSize(ISize(512, 1));
306 pass->SetThreadGroupSize(ISize(512, 1));
307
308 CS1::Input<kCount1> input_1;
309 input_1.count = kCount1;
310 for (size_t i = 0; i < kCount1; i++) {
311 input_1.elements[i] = i;
312 }
313
314 CS2::Input<kCount2> input_2;
315 input_2.count = kCount2;
316 for (size_t i = 0; i < kCount2; i++) {
317 input_2.elements[i] = i;
318 }
319
320 auto output_buffer_1 = CreateHostVisibleDeviceBuffer<CS1::Output<kCount2>>(
321 context, "Output Buffer Stage 1");
322 auto output_buffer_2 = CreateHostVisibleDeviceBuffer<CS2::Output<kCount2>>(
323 context, "Output Buffer Stage 2");
324
325 {
326 ComputeCommand cmd;
327 cmd.pipeline = compute_pipeline_1;
328
329 CS1::BindInput(cmd,
330 pass->GetTransientsBuffer().EmplaceStorageBuffer(input_1));
331 CS1::BindOutput(cmd, output_buffer_1->AsBufferView());
332
333 ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
334 }
335
336 {
337 ComputeCommand cmd;
338 cmd.pipeline = compute_pipeline_2;
339
340 CS1::BindInput(cmd, output_buffer_1->AsBufferView());
341 CS2::BindOutput(cmd, output_buffer_2->AsBufferView());
342 ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
343 }
344
345 ASSERT_TRUE(pass->EncodeCommands());
346
347 fml::AutoResetWaitableEvent latch;
348 ASSERT_TRUE(cmd_buffer->SubmitCommands([&latch, &output_buffer_1,
349 &output_buffer_2](
350 CommandBuffer::Status status) {
351 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
352
353 CS1::Output<kCount2>* output_1 = reinterpret_cast<CS1::Output<kCount2>*>(
354 output_buffer_1->AsBufferView().contents);
355 EXPECT_TRUE(output_1);
356 EXPECT_EQ(output_1->count, 10u);
357 EXPECT_THAT(output_1->elements,
358 ::testing::ElementsAre(0, 0, 2, 3, 4, 6, 6, 9, 8, 12));
359
360 CS2::Output<kCount2>* output_2 = reinterpret_cast<CS2::Output<kCount2>*>(
361 output_buffer_2->AsBufferView().contents);
362 EXPECT_TRUE(output_2);
363 EXPECT_EQ(output_2->count, 10u);
364 EXPECT_THAT(output_2->elements,
365 ::testing::ElementsAre(0, 0, 4, 6, 8, 12, 12, 18, 16, 24));
366
367 latch.Signal();
368 }));
369
370 latch.Wait();
371 }

References impeller::kCount1, and impeller::ComputeCommand::pipeline.

## ◆ TEST_P() [207/384]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | ReturnsEarlyWhenAnyGridDimensionIsZero |
| ) |  |

Definition at line 450 of file compute_unittests.cc.

450 {
451 using CS = SampleComputeShader;
452 auto context = GetContext();
453 ASSERT_TRUE(context);
454 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
455
456 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
457 auto pipeline_desc =
458 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
459 ASSERT_TRUE(pipeline_desc.has_value());
460 auto compute_pipeline =
461 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
462 ASSERT_TRUE(compute_pipeline);
463
464 auto cmd_buffer = context->CreateCommandBuffer();
465 auto pass = cmd_buffer->CreateComputePass();
466 ASSERT_TRUE(pass && pass->IsValid());
467
468 static constexpr size_t kCount = 5;
469
470 // Intentionally making the grid size zero in one dimension. No GPU will
471 // tolerate this.
472 pass->SetGridSize(ISize(0, 1));
473 pass->SetThreadGroupSize(ISize(0, 1));
474
475 ComputeCommand cmd;
476 cmd.pipeline = compute_pipeline;
477
478 CS::Info info{.count = kCount};
479 CS::Input0<kCount> input_0;
480 CS::Input1<kCount> input_1;
481 for (size_t i = 0; i < kCount; i++) {
482 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
483 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
484 }
485
486 input_0.fixed_array[1] = IPoint32(2, 2);
487 input_1.fixed_array[0] = UintPoint32(3, 3);
488 input_0.some_int = 5;
489 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
490
491 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
492 context, "Output Buffer");
493
494 CS::BindInfo(cmd, pass->GetTransientsBuffer().EmplaceUniform(info));
495 CS::BindInput0(cmd,
496 pass->GetTransientsBuffer().EmplaceStorageBuffer(input_0));
497 CS::BindInput1(cmd,
498 pass->GetTransientsBuffer().EmplaceStorageBuffer(input_1));
499 CS::BindOutput(cmd, output_buffer->AsBufferView());
500
501 ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
502 ASSERT_FALSE(pass->EncodeCommands());
503 }

References impeller::ComputeCommand::pipeline.

## ◆ TEST_P() [208/384]

impeller::testing::TEST_P | ( | DirectionalGaussianBlurFilterContentsTest | ,
|  | CoverageWithEffectTransform |
| ) |  |

Definition at line 39 of file directional_gaussian_blur_filter_contents_unittests.cc.

39 {
40 TextureDescriptor desc = {
41 .format = PixelFormat::kB8G8R8A8UNormInt,
42 .size = ISize(100, 100),
43 };
44 Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
45 auto contents = std::make_unique<DirectionalGaussianBlurFilterContents>();
46 contents->SetSigma(Sigma{sigma_radius_1});
47 contents->SetDirection({1.0, 0.0});
48 std::shared_ptr<Texture> texture =
49 GetContentContext()->GetContext()->GetResourceAllocator()->CreateTexture(
50 desc);
51 FilterInput::Vector inputs = {FilterInput::Make(texture)};
52 Entity entity;
53 entity.SetTransform(Matrix::MakeTranslation({100, 100, 0}));
54 std::optional<Rect> coverage = contents->GetFilterCoverage(
55 inputs, entity, /*effect_transform=*/Matrix::MakeScale({2.0, 2.0, 1.0}));
56 EXPECT_TRUE(coverage.has_value());
57 if (coverage.has_value()) {
58 EXPECT_NEAR(coverage->GetLeft(), 100 - 2,
59 0.5); // Higher tolerance for sigma scaling.
60 EXPECT_NEAR(coverage->GetTop(), 100, 0.01);
61 EXPECT_NEAR(coverage->GetRight(), 200 + 2,
62 0.5); // Higher tolerance for sigma scaling.
63 EXPECT_NEAR(coverage->GetBottom(), 200, 0.01);
64 }
65 }

References impeller::TextureDescriptor::format, impeller::kB8G8R8A8UNormInt, impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [209/384]

impeller::testing::TEST_P | ( | DirectionalGaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverage |
| ) |  |

Definition at line 91 of file directional_gaussian_blur_filter_contents_unittests.cc.

92 {
93 TextureDescriptor desc = {
94 .storage_mode = StorageMode::kDevicePrivate,
95 .format = PixelFormat::kB8G8R8A8UNormInt,
96 .size = ISize(100, 100),
97 };
98 std::shared_ptr<Texture> texture =
99 GetContentContext()->GetContext()->GetResourceAllocator()->CreateTexture(
100 desc);
101 Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
102 auto contents = std::make_unique<DirectionalGaussianBlurFilterContents>();
103 contents->SetSigma(Sigma{sigma_radius_1});
104 contents->SetDirection({1.0, 0.0});
105 contents->SetInputs({FilterInput::Make(texture)});
106 std::shared_ptr<ContentContext> renderer = GetContentContext();
107
108 Entity entity;
109 std::optional<Entity> result =
110 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
111 EXPECT_TRUE(result.has_value());
112 if (result.has_value()) {
113 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
114 std::optional<Rect> result_coverage = result.value().GetCoverage();
115 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
116 EXPECT_TRUE(result_coverage.has_value());
117 EXPECT_TRUE(contents_coverage.has_value());
118 if (result_coverage.has_value() && contents_coverage.has_value()) {
119 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
120 // The precision on this blur is kind of off, thus the tolerance.
121 EXPECT_NEAR(result_coverage.value().GetLeft(), -1.f, 0.1f);
122 EXPECT_NEAR(result_coverage.value().GetTop(), 0.f, 0.001f);
123 EXPECT_NEAR(result_coverage.value().GetRight(), 101.f, 0.1f);
124 EXPECT_NEAR(result_coverage.value().GetBottom(), 100.f, 0.001f);
125 }
126 }
127 }

References impeller::kB8G8R8A8UNormInt, impeller::kDevicePrivate, impeller::kSourceOver, impeller::FilterInput::Make(), RectNear(), and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [210/384]

impeller::testing::TEST_P | ( | DirectionalGaussianBlurFilterContentsTest | ,
|  | RenderNoCoverage |
| ) |  |

Definition at line 78 of file directional_gaussian_blur_filter_contents_unittests.cc.

78 {
79 Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
80 auto contents = std::make_unique<DirectionalGaussianBlurFilterContents>();
81 contents->SetSigma(Sigma{sigma_radius_1});
82 contents->SetDirection({1.0, 0.0});
83 std::shared_ptr<ContentContext> renderer = GetContentContext();
84 Entity entity;
85 Rect coverage_hint = Rect::MakeLTRB(0, 0, 0, 0);
86 std::optional<Entity> result =
87 contents->GetEntity(*renderer, entity, coverage_hint);
88 ASSERT_FALSE(result.has_value());
89 }

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

## ◆ TEST_P() [211/384]

impeller::testing::TEST_P | ( | DirectionalGaussianBlurFilterContentsTest | ,
|  | TextureContentsWithDestinationRect |
| ) |  |

Definition at line 129 of file directional_gaussian_blur_filter_contents_unittests.cc.

130 {
131 TextureDescriptor desc = {
132 .storage_mode = StorageMode::kDevicePrivate,
133 .format = PixelFormat::kB8G8R8A8UNormInt,
134 .size = ISize(100, 100),
135 };
136
137 std::shared_ptr<Texture> texture =
138 GetContentContext()->GetContext()->GetResourceAllocator()->CreateTexture(
139 desc);
140 auto texture_contents = std::make_shared<TextureContents>();
141 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
142 texture_contents->SetTexture(texture);
143 texture_contents->SetDestinationRect(Rect::MakeXYWH(
144 50, 40, texture->GetSize().width, texture->GetSize().height));
145
146 Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
147 auto contents = std::make_unique<DirectionalGaussianBlurFilterContents>();
148 contents->SetSigma(Sigma{sigma_radius_1});
149 contents->SetDirection({1.0, 0.0});
150 contents->SetInputs({FilterInput::Make(texture_contents)});
151 std::shared_ptr<ContentContext> renderer = GetContentContext();
152
153 Entity entity;
154 std::optional<Entity> result =
155 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
156 EXPECT_TRUE(result.has_value());
157 if (result.has_value()) {
158 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
159 std::optional<Rect> result_coverage = result.value().GetCoverage();
160 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
161 EXPECT_TRUE(result_coverage.has_value());
162 EXPECT_TRUE(contents_coverage.has_value());
163 if (result_coverage.has_value() && contents_coverage.has_value()) {
164 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
165 // The precision on this blur is kind of off, thus the tolerance.
166 EXPECT_NEAR(result_coverage.value().GetLeft(), 49.f, 0.1f);
167 EXPECT_NEAR(result_coverage.value().GetTop(), 40.f, 0.001f);
168 EXPECT_NEAR(result_coverage.value().GetRight(), 151.f, 0.1f);
169 EXPECT_NEAR(result_coverage.value().GetBottom(), 140.f, 0.001f);
170 }
171 }
172 }

References impeller::kB8G8R8A8UNormInt, impeller::kDevicePrivate, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), RectNear(), and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [212/384]

impeller::testing::TEST_P | ( | DirectionalGaussianBlurFilterContentsTest | ,
|  | TextureContentsWithDestinationRectScaled |
| ) |  |

Definition at line 174 of file directional_gaussian_blur_filter_contents_unittests.cc.

175 {
176 TextureDescriptor desc = {
177 .storage_mode = StorageMode::kDevicePrivate,
178 .format = PixelFormat::kB8G8R8A8UNormInt,
179 .size = ISize(100, 100),
180 };
181
182 std::shared_ptr<Texture> texture =
183 GetContentContext()->GetContext()->GetResourceAllocator()->CreateTexture(
184 desc);
185 auto texture_contents = std::make_shared<TextureContents>();
186 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
187 texture_contents->SetTexture(texture);
188 texture_contents->SetDestinationRect(Rect::MakeXYWH(
189 50, 40, texture->GetSize().width, texture->GetSize().height));
190
191 Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
192 auto contents = std::make_unique<DirectionalGaussianBlurFilterContents>();
193 contents->SetSigma(Sigma{sigma_radius_1});
194 contents->SetDirection({1.0, 0.0});
195 contents->SetInputs({FilterInput::Make(texture_contents)});
196 std::shared_ptr<ContentContext> renderer = GetContentContext();
197
198 Entity entity;
199 entity.SetTransform(Matrix::MakeScale({2.0, 2.0, 1.0}));
200 std::optional<Entity> result =
201 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
202 EXPECT_TRUE(result.has_value());
203 if (result.has_value()) {
204 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
205 std::optional<Rect> result_coverage = result.value().GetCoverage();
206 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
207 EXPECT_TRUE(result_coverage.has_value());
208 EXPECT_TRUE(contents_coverage.has_value());
209 if (result_coverage.has_value() && contents_coverage.has_value()) {
210 // The precision on this blur is kind of off, thus the tolerance.
211
212 EXPECT_NEAR(result_coverage.value().GetLeft(), 98.f, 0.1f);
213 EXPECT_NEAR(result_coverage.value().GetTop(), 80.f, 0.001f);
214 EXPECT_NEAR(result_coverage.value().GetRight(), 302.f, 0.1f);
215 EXPECT_NEAR(result_coverage.value().GetBottom(), 280.f, 0.001f);
216
217 EXPECT_NEAR(contents_coverage.value().GetLeft(), 98.f, 0.1f);
218 EXPECT_NEAR(contents_coverage.value().GetTop(), 80.f, 0.001f);
219 EXPECT_NEAR(contents_coverage.value().GetRight(), 302.f, 0.1f);
220 EXPECT_NEAR(contents_coverage.value().GetBottom(), 280.f, 0.001f);
221 }
222 }
223 }

References impeller::kB8G8R8A8UNormInt, impeller::kDevicePrivate, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Entity::SetTransform(), and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [213/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanBlendDstOverAndDstCorrectly |
| ) |  |

Definition at line 1264 of file dl_unittests.cc.

1264 {
1265 flutter::DisplayListBuilder builder;
1266
1267 {
1268 builder.SaveLayer(nullptr, nullptr);
1269 builder.Translate(100, 100);
1270 flutter::DlPaint paint;
1271 paint.setColor(flutter::DlColor::kRed());
1272 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1273 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1274 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
1275 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1276 builder.Restore();
1277 }
1278 {
1279 builder.SaveLayer(nullptr, nullptr);
1280 builder.Translate(300, 100);
1281 flutter::DlPaint paint;
1282 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1283 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1284 paint.setColor(flutter::DlColor::kRed());
1285 paint.setBlendMode(flutter::DlBlendMode::kDstOver);
1286 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1287 builder.Restore();
1288 }
1289 {
1290 builder.SaveLayer(nullptr, nullptr);
1291 builder.Translate(100, 300);
1292 flutter::DlPaint paint;
1293 paint.setColor(flutter::DlColor::kRed());
1294 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1295 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1296 paint.setBlendMode(flutter::DlBlendMode::kSrc);
1297 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1298 builder.Restore();
1299 }
1300 {
1301 builder.SaveLayer(nullptr, nullptr);
1302 builder.Translate(300, 300);
1303 flutter::DlPaint paint;
1304 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1305 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1306 paint.setColor(flutter::DlColor::kRed());
1307 paint.setBlendMode(flutter::DlBlendMode::kDst);
1308 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1309 builder.Restore();
1310 }
1311
1312 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1313 }

## ◆ TEST_P() [214/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanClampTheResultingColorOfColorMatrixFilter |
| ) |  |

Definition at line 628 of file dl_unittests.cc.

628 {
629 auto texture = CreateTextureForFixture("boston.jpg");
630 const float inner_color_matrix[20] = {
631 1, 0, 0, 0, 0, //
632 0, 1, 0, 0, 0, //
633 0, 0, 1, 0, 0, //
634 0, 0, 0, 2, 0, //
635 };
636 const float outer_color_matrix[20] = {
637 1, 0, 0, 0, 0, //
638 0, 1, 0, 0, 0, //
639 0, 0, 1, 0, 0, //
640 0, 0, 0, 0.5, 0, //
641 };
642 auto inner_color_filter =
643 std::make_shared<flutter::DlMatrixColorFilter>(inner_color_matrix);
644 auto outer_color_filter =
645 std::make_shared<flutter::DlMatrixColorFilter>(outer_color_matrix);
646 auto inner =
647 std::make_shared<flutter::DlColorFilterImageFilter>(inner_color_filter);
648 auto outer =
649 std::make_shared<flutter::DlColorFilterImageFilter>(outer_color_filter);
650 auto compose = std::make_shared<flutter::DlComposeImageFilter>(outer, inner);
651
652 flutter::DisplayListBuilder builder;
653 flutter::DlPaint paint;
654 paint.setImageFilter(compose.get());
655 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
656 flutter::DlImageSampling::kNearestNeighbor, &paint);
657 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
658 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [215/384]

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

Definition at line 975 of file dl_unittests.cc.

975 {
976 constexpr Scalar hexagon_radius = 125;
977 auto hex_start = Point(200.0, -hexagon_radius + 200.0);
978 auto center_to_flat = 1.73 / 2 * hexagon_radius;
979
980 // clang-format off
981 std::vector<SkPoint> vertices = {
982 SkPoint::Make(hex_start.x, hex_start.y),
983 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 0.5 * hexagon_radius),
984 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
985 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
986 SkPoint::Make(hex_start.x, hex_start.y + 2 * hexagon_radius),
987 SkPoint::Make(hex_start.x, hex_start.y + 2 * hexagon_radius),
988 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
989 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
990 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 0.5 * hexagon_radius)
991 };
992 // clang-format on
993 auto paint = flutter::DlPaint(flutter::DlColor::kDarkGrey());
994 auto dl_vertices = flutter::DlVertices::Make(
995 flutter::DlVertexMode::kTriangleFan, vertices.size(), vertices.data(),
996 nullptr, nullptr);
997 flutter::DisplayListBuilder builder;
998 builder.DrawVertices(dl_vertices, flutter::DlBlendMode::kSrcOver, paint);
999 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1000 }

## ◆ TEST_P() [216/384]

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

Definition at line 418 of file dl_unittests.cc.

418 {
419 flutter::DisplayListBuilder builder;
420 flutter::DlPaint paint;
421
422 paint.setColor(flutter::DlColor::kRed());
423 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
424 paint.setStrokeWidth(10);
425
426 builder.Translate(300, 300);
427
428 // Move to (50, 50) and draw lines from:
429 // 1. (50, height)
430 // 2. (width, height)
431 // 3. (width, 50)
432 SkPath path;
433 path.moveTo(50, 50);
434 path.lineTo(50, 100);
435 path.lineTo(100, 100);
436 path.lineTo(100, 50);
437 builder.DrawPath(path, paint);
438
439 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
440 }

## ◆ TEST_P() [217/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawArc |
| ) |  |

Definition at line 165 of file dl_unittests.cc.

165 {
166 auto callback = [&]() {
167 static float start_angle = 45;
168 static float sweep_angle = 270;
169 static float stroke_width = 10;
170 static bool use_center = true;
171
172 static int selected_cap = 0;
173 const char* cap_names[] = {"Butt", "Round", "Square"};
174 flutter::DlStrokeCap cap;
175
176 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
177 ImGui::SliderFloat("Start angle", &start_angle, -360, 360);
178 ImGui::SliderFloat("Sweep angle", &sweep_angle, -360, 360);
179 ImGui::SliderFloat("Stroke width", &stroke_width, 0, 300);
180 ImGui::Combo("Cap", &selected_cap, cap_names,
181 sizeof(cap_names) / sizeof(char*));
182 ImGui::Checkbox("Use center", &use_center);
183 ImGui::End();
184
185 switch (selected_cap) {
186 case 0:
187 cap = flutter::DlStrokeCap::kButt;
188 break;
189 case 1:
190 cap = flutter::DlStrokeCap::kRound;
191 break;
192 case 2:
193 cap = flutter::DlStrokeCap::kSquare;
194 break;
195 default:
196 cap = flutter::DlStrokeCap::kButt;
197 break;
198 }
199
200 auto [p1, p2] = IMPELLER_PLAYGROUND_LINE(
201 Point(200, 200), Point(400, 400), 20, Color::White(), Color::White());
202
203 flutter::DisplayListBuilder builder;
204 flutter::DlPaint paint;
205
206 Vector2 scale = GetContentScale();
207 builder.Scale(scale.x, scale.y);
208 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
209 paint.setStrokeCap(cap);
210 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
211 paint.setStrokeMiter(10);
212 auto rect = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
213 paint.setColor(flutter::DlColor::kGreen());
214 paint.setStrokeWidth(2);
215 builder.DrawRect(rect, paint);
216 paint.setColor(flutter::DlColor::kRed());
217 paint.setStrokeWidth(stroke_width);
218 builder.DrawArc(rect, start_angle, sweep_angle, use_center, paint);
219
220 return builder.Build();
221 };
222 ASSERT_TRUE(OpenPlaygroundHere(callback));
223 }

References IMPELLER_PLAYGROUND_LINE, impeller::Color::White(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [218/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawBackdropFilter |
| ) |  |

Definition at line 660 of file dl_unittests.cc.

660 {
661 auto texture = CreateTextureForFixture("embarcadero.jpg");
662
663 auto callback = [&]() {
664 static float sigma[] = {10, 10};
665 static float ctm_scale = 1;
666 static bool use_bounds = true;
667 static bool draw_circle = true;
668 static bool add_clip = true;
669
670 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
671 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
672 ImGui::SliderFloat("Scale", &ctm_scale, 0, 10);
673 ImGui::NewLine();
674 ImGui::TextWrapped(
675 "If everything is working correctly, none of the options below should "
676 "impact the filter's appearance.");
677 ImGui::Checkbox("Use SaveLayer bounds", &use_bounds);
678 ImGui::Checkbox("Draw child element", &draw_circle);
679 ImGui::Checkbox("Add pre-clip", &add_clip);
680 ImGui::End();
681
682 flutter::DisplayListBuilder builder;
683
684 Vector2 scale = ctm_scale * GetContentScale();
685 builder.Scale(scale.x, scale.y);
686
687 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
688 flutter::DlTileMode::kClamp);
689
690 std::optional<SkRect> bounds;
691 if (use_bounds) {
692 auto [p1, p2] = IMPELLER_PLAYGROUND_LINE(
693 Point(350, 150), Point(800, 600), 20, Color::White(), Color::White());
694 bounds = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
695 }
696
697 // Insert a clip to test that the backdrop filter handles stencil depths > 0
698 // correctly.
699 if (add_clip) {
700 builder.ClipRect(SkRect::MakeLTRB(0, 0, 99999, 99999),
701 flutter::DlCanvas::ClipOp::kIntersect, true);
702 }
703
704 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
705 flutter::DlImageSampling::kNearestNeighbor, nullptr);
706 builder.SaveLayer(bounds.has_value() ? &bounds.value() : nullptr, nullptr,
707 &filter);
708
709 if (draw_circle) {
710 auto circle_center =
711 IMPELLER_PLAYGROUND_POINT(Point(500, 400), 20, Color::Red());
712
713 flutter::DlPaint paint;
714 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
715 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
716 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
717 paint.setStrokeWidth(10);
718 paint.setColor(flutter::DlColor::kRed().withAlpha(100));
719 builder.DrawCircle({circle_center.x, circle_center.y}, 100, paint);
720 }
721
722 return builder.Build();
723 };
724
725 ASSERT_TRUE(OpenPlaygroundHere(callback));
726 }

References IMPELLER_PLAYGROUND_LINE, IMPELLER_PLAYGROUND_POINT, impeller::DlImageImpeller::Make(), impeller::Color::Red(), impeller::Color::White(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [219/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCapsAndJoins |
| ) |  |

Definition at line 119 of file dl_unittests.cc.

119 {
120 flutter::DisplayListBuilder builder;
121 flutter::DlPaint paint;
122
123 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
124 paint.setStrokeWidth(30);
125 paint.setColor(flutter::DlColor::kRed());
126
127 auto path =
128 SkPathBuilder{}.moveTo(-50, 0).lineTo(0, -50).lineTo(50, 0).snapshot();
129
130 builder.Translate(100, 100);
131 {
132 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
133 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
134 paint.setStrokeMiter(4);
135 builder.DrawPath(path, paint);
136 }
137
138 {
139 builder.Save();
140 builder.Translate(0, 100);
141 // The joint in the path is 45 degrees. A miter length of 1 convert to a
142 // bevel in this case.
143 paint.setStrokeMiter(1);
144 builder.DrawPath(path, paint);
145 builder.Restore();
146 }
147
148 builder.Translate(150, 0);
149 {
150 paint.setStrokeCap(flutter::DlStrokeCap::kSquare);
151 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
152 builder.DrawPath(path, paint);
153 }
154
155 builder.Translate(150, 0);
156 {
157 paint.setStrokeCap(flutter::DlStrokeCap::kRound);
158 paint.setStrokeJoin(flutter::DlStrokeJoin::kRound);
159 builder.DrawPath(path, paint);
160 }
161
162 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
163 }

## ◆ TEST_P() [220/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCorrectlyWithColorFilterAndImageFilter |
| ) |  |

Definition at line 1315 of file dl_unittests.cc.

1315 {
1316 flutter::DisplayListBuilder builder;
1317 const float green_color_matrix[20] = {
1318 0, 0, 0, 0, 0, //
1319 0, 0, 0, 0, 1, //
1320 0, 0, 0, 0, 0, //
1321 0, 0, 0, 1, 0, //
1322 };
1323 const float blue_color_matrix[20] = {
1324 0, 0, 0, 0, 0, //
1325 0, 0, 0, 0, 0, //
1326 0, 0, 0, 0, 1, //
1327 0, 0, 0, 1, 0, //
1328 };
1329 auto green_color_filter =
1330 std::make_shared<flutter::DlMatrixColorFilter>(green_color_matrix);
1331 auto blue_color_filter =
1332 std::make_shared<flutter::DlMatrixColorFilter>(blue_color_matrix);
1333 auto blue_image_filter =
1334 std::make_shared<flutter::DlColorFilterImageFilter>(blue_color_filter);
1335
1336 flutter::DlPaint paint;
1337 paint.setColor(flutter::DlColor::kRed());
1338 paint.setColorFilter(green_color_filter);
1339 paint.setImageFilter(blue_image_filter);
1340 builder.DrawRect(SkRect::MakeLTRB(100, 100, 500, 500), paint);
1341 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1342 }

## ◆ TEST_P() [221/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawImage |
| ) |  |

Definition at line 111 of file dl_unittests.cc.

111 {
112 auto texture = CreateTextureForFixture("embarcadero.jpg");
113 flutter::DisplayListBuilder builder;
114 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
115 flutter::DlImageSampling::kNearestNeighbor, nullptr);
116 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
117 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [222/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImage |
| ) |  |

Definition at line 728 of file dl_unittests.cc.

728 {
729 // Image is drawn with corners to scale and center pieces stretched to fit.
730 auto texture = CreateTextureForFixture("embarcadero.jpg");
731 flutter::DisplayListBuilder builder;
732 auto size = texture->GetSize();
733 builder.DrawImageNine(
734 DlImageImpeller::Make(texture),
735 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
736 size.height * 3 / 4),
737 SkRect::MakeLTRB(0, 0, size.width * 2, size.height * 2),
738 flutter::DlFilterMode::kNearest, nullptr);
739 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
740 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [223/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterBiggerThanDest |
| ) |  |

Definition at line 774 of file dl_unittests.cc.

774 {
775 // Edge case, the width and height of the corners does not leave any
776 // room for the center slices. Only the corners are displayed.
777 auto texture = CreateTextureForFixture("embarcadero.jpg");
778 flutter::DisplayListBuilder builder;
779 auto size = texture->GetSize();
780 builder.DrawImageNine(
781 DlImageImpeller::Make(texture),
782 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
783 size.height * 3 / 4),
784 SkRect::MakeLTRB(0, 0, size.width / 2, size.height / 2),
785 flutter::DlFilterMode::kNearest, nullptr);
786 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
787 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [224/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterHeightBiggerThanDest |
| ) |  |

Definition at line 758 of file dl_unittests.cc.

758 {
759 // Edge case, the height of the corners does not leave any room for the
760 // center slice. The center (across the horizontal axis) is folded out of the
761 // resulting image.
762 auto texture = CreateTextureForFixture("embarcadero.jpg");
763 flutter::DisplayListBuilder builder;
764 auto size = texture->GetSize();
765 builder.DrawImageNine(
766 DlImageImpeller::Make(texture),
767 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
768 size.height * 3 / 4),
769 SkRect::MakeLTRB(0, 0, size.width, size.height / 2),
770 flutter::DlFilterMode::kNearest, nullptr);
771 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
772 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [225/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterWidthBiggerThanDest |
| ) |  |

Definition at line 742 of file dl_unittests.cc.

742 {
743 // Edge case, the width of the corners does not leave any room for the
744 // center slice. The center (across the vertical axis) is folded out of the
745 // resulting image.
746 auto texture = CreateTextureForFixture("embarcadero.jpg");
747 flutter::DisplayListBuilder builder;
748 auto size = texture->GetSize();
749 builder.DrawImageNine(
750 DlImageImpeller::Make(texture),
751 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
752 size.height * 3 / 4),
753 SkRect::MakeLTRB(0, 0, size.width / 2, size.height),
754 flutter::DlFilterMode::kNearest, nullptr);
755 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
756 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [226/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCornersScaledDown |
| ) |  |

Definition at line 789 of file dl_unittests.cc.

789 {
790 // Edge case, there is not enough room for the corners to be drawn
791 // without scaling them down.
792 auto texture = CreateTextureForFixture("embarcadero.jpg");
793 flutter::DisplayListBuilder builder;
794 auto size = texture->GetSize();
795 builder.DrawImageNine(
796 DlImageImpeller::Make(texture),
797 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
798 size.height * 3 / 4),
799 SkRect::MakeLTRB(0, 0, size.width / 4, size.height / 4),
800 flutter::DlFilterMode::kNearest, nullptr);
801 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
802 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [227/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPaintWithColorSource |
| ) |  |

Definition at line 1212 of file dl_unittests.cc.

1212 {
1213 const flutter::DlColor colors[2] = {
1214 flutter::DlColor(0xFFF44336),
1215 flutter::DlColor(0xFF2196F3),
1216 };
1217 const float stops[2] = {0.0, 1.0};
1218 flutter::DlPaint paint;
1219 flutter::DisplayListBuilder builder;
1220 auto clip_bounds = SkRect::MakeWH(300.0, 300.0);
1221 builder.Save();
1222 builder.Translate(100, 100);
1223 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1224 auto linear =
1225 flutter::DlColorSource::MakeLinear({0.0, 0.0}, {100.0, 100.0}, 2, colors,
1226 stops, flutter::DlTileMode::kRepeat);
1227 paint.setColorSource(linear);
1228 builder.DrawPaint(paint);
1229 builder.Restore();
1230
1231 builder.Save();
1232 builder.Translate(500, 100);
1233 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1234 auto radial = flutter::DlColorSource::MakeRadial(
1235 {100.0, 100.0}, 100.0, 2, colors, stops, flutter::DlTileMode::kRepeat);
1236 paint.setColorSource(radial);
1237 builder.DrawPaint(paint);
1238 builder.Restore();
1239
1240 builder.Save();
1241 builder.Translate(100, 500);
1242 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1243 auto sweep =
1244 flutter::DlColorSource::MakeSweep({100.0, 100.0}, 180.0, 270.0, 2, colors,
1245 stops, flutter::DlTileMode::kRepeat);
1246 paint.setColorSource(sweep);
1247 builder.DrawPaint(paint);
1248 builder.Restore();
1249
1250 builder.Save();
1251 builder.Translate(500, 500);
1252 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1253 auto texture = CreateTextureForFixture("table_mountain_nx.png");
1254 auto image = std::make_shared<flutter::DlImageColorSource>(
1255 DlImageImpeller::Make(texture), flutter::DlTileMode::kRepeat,
1256 flutter::DlTileMode::kRepeat);
1257 paint.setColorSource(image);
1258 builder.DrawPaint(paint);
1259 builder.Restore();
1260
1261 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1262 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [228/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPoints |
| ) |  |

Definition at line 804 of file dl_unittests.cc.

804 {
805 flutter::DisplayListBuilder builder;
806 SkPoint points[7] = {
807 {0, 0}, //
808 {100, 100}, //
809 {100, 0}, //
810 {0, 100}, //
811 {0, 0}, //
812 {48, 48}, //
813 {52, 52}, //
814 };
815 std::vector<flutter::DlStrokeCap> caps = {
816 flutter::DlStrokeCap::kButt,
817 flutter::DlStrokeCap::kRound,
818 flutter::DlStrokeCap::kSquare,
819 };
820 flutter::DlPaint paint =
821 flutter::DlPaint() //
822 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
823 .setStrokeWidth(20);
824 builder.Translate(50, 50);
825 for (auto cap : caps) {
826 paint.setStrokeCap(cap);
827 builder.Save();
828 builder.DrawPoints(flutter::DlCanvas::PointMode::kPoints, 7, points, paint);
829 builder.Translate(150, 0);
830 builder.DrawPoints(flutter::DlCanvas::PointMode::kLines, 5, points, paint);
831 builder.Translate(150, 0);
832 builder.DrawPoints(flutter::DlCanvas::PointMode::kPolygon, 5, points,
833 paint);
834 builder.Restore();
835 builder.Translate(0, 150);
836 }
837 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
838 }

## ◆ TEST_P() [229/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRect |
| ) |  |

Definition at line 62 of file dl_unittests.cc.

62 {
63 flutter::DisplayListBuilder builder;
64 builder.DrawRect(SkRect::MakeXYWH(10, 10, 100, 100),
65 flutter::DlPaint(flutter::DlColor::kBlue()));
66 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
67 }

## ◆ TEST_P() [230/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRectWithLinearToSrgbColorFilter |
| ) |  |

Definition at line 1196 of file dl_unittests.cc.

1196 {
1197 flutter::DlPaint paint;
1198 paint.setColor(flutter::DlColor(0xFF2196F3).withAlpha(128));
1199 flutter::DisplayListBuilder builder;
1200 paint.setColorFilter(
1201 flutter::DlLinearToSrgbGammaColorFilter::kInstance.get());
1202 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
1203 builder.Translate(0, 200);
1204
1205 paint.setColorFilter(
1206 flutter::DlSrgbToLinearGammaColorFilter::kInstance.get());
1207 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
1208
1209 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1210 }

## ◆ TEST_P() [231/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawShadow |
| ) |  |

Definition at line 863 of file dl_unittests.cc.

863 {
864 flutter::DisplayListBuilder builder;
865 flutter::DlPaint paint;
866
867 auto content_scale = GetContentScale() * 0.8;
868 builder.Scale(content_scale.x, content_scale.y);
869
870 constexpr size_t star_spikes = 5;
871 constexpr SkScalar half_spike_rotation = kPi / star_spikes;
872 constexpr SkScalar radius = 40;
873 constexpr SkScalar spike_size = 10;
874 constexpr SkScalar outer_radius = radius + spike_size;
875 constexpr SkScalar inner_radius = radius - spike_size;
876 std::array<SkPoint, star_spikes * 2> star;
877 for (size_t i = 0; i < star_spikes; i++) {
878 const SkScalar rotation = half_spike_rotation * i * 2;
879 star[i * 2] = SkPoint::Make(50 + std::sin(rotation) * outer_radius,
880 50 - std::cos(rotation) * outer_radius);
881 star[i * 2 + 1] = SkPoint::Make(
882 50 + std::sin(rotation + half_spike_rotation) * inner_radius,
883 50 - std::cos(rotation + half_spike_rotation) * inner_radius);
884 }
885
886 std::array<SkPath, 4> paths = {
887 SkPath{}.addRect(SkRect::MakeXYWH(0, 0, 200, 100)),
888 SkPath{}.addRRect(
889 SkRRect::MakeRectXY(SkRect::MakeXYWH(20, 0, 200, 100), 30, 30)),
890 SkPath{}.addCircle(100, 50, 50),
891 SkPath{}.addPoly(star.data(), star.size(), true),
892 };
893 paint.setColor(flutter::DlColor::kWhite());
894 builder.DrawPaint(paint);
895 paint.setColor(flutter::DlColor::kCyan());
896 builder.Translate(100, 50);
897 for (size_t x = 0; x < paths.size(); x++) {
898 builder.Save();
899 for (size_t y = 0; y < 6; y++) {
900 builder.DrawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false,
901 1);
902 builder.DrawPath(paths[x], paint);
903 builder.Translate(0, 150);
904 }
905 builder.Restore();
906 builder.Translate(250, 0);
907 }
908
909 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
910 }

References impeller::kPi.

## ◆ TEST_P() [232/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawStrokedText |
| ) |  |

Definition at line 478 of file dl_unittests.cc.

478 {
479 flutter::DisplayListBuilder builder;
480 flutter::DlPaint paint;
481
482 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
483 paint.setColor(flutter::DlColor::kRed());
484 builder.DrawTextBlob(
485 SkTextBlob::MakeFromString("stoked about stroked text", CreateTestFont()),
486 250, 250, paint);
487
488 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
489 }

## ◆ TEST_P() [233/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextBlob |
| ) |  |

Definition at line 69 of file dl_unittests.cc.

69 {
70 flutter::DisplayListBuilder builder;
71 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
72 100, 100, flutter::DlPaint(flutter::DlColor::kBlue()));
73 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
74 }

## ◆ TEST_P() [234/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextBlobWithGradient |
| ) |  |

Definition at line 76 of file dl_unittests.cc.

76 {
77 flutter::DisplayListBuilder builder;
78
79 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
80 flutter::DlColor::kRed()};
81 const float stops[2] = {0.0, 1.0};
82
83 auto linear = flutter::DlColorSource::MakeLinear({0.0, 0.0}, {300.0, 300.0},
84 2, colors.data(), stops,
85 flutter::DlTileMode::kClamp);
86 flutter::DlPaint paint;
87 paint.setColorSource(linear);
88
89 builder.DrawTextBlob(
90 SkTextBlob::MakeFromString("Hello World", CreateTestFont()), 100, 100,
91 paint);
92 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
93 }

## ◆ TEST_P() [235/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextWithSaveLayer |
| ) |  |

Definition at line 95 of file dl_unittests.cc.

95 {
96 flutter::DisplayListBuilder builder;
97 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
98 100, 100, flutter::DlPaint(flutter::DlColor::kRed()));
99
100 flutter::DlPaint save_paint;
101 float alpha = 0.5;
102 save_paint.setAlpha(static_cast<uint8_t>(255 * alpha));
103 builder.SaveLayer(nullptr, &save_paint);
104 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello with half alpha",
105 CreateTestFontOfSize(100)),
106 100, 300, flutter::DlPaint(flutter::DlColor::kRed()));
107 builder.Restore();
108 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
109 }

## ◆ TEST_P() [236/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithBlendColorFilter |
| ) |  |

Definition at line 530 of file dl_unittests.cc.

530 {
531 auto texture = CreateTextureForFixture("embarcadero.jpg");
532 flutter::DisplayListBuilder builder;
533 flutter::DlPaint paint;
534
535 // Pipeline blended image.
536 {
537 auto filter = flutter::DlBlendColorFilter(flutter::DlColor::kYellow(),
538 flutter::DlBlendMode::kModulate);
539 paint.setColorFilter(&filter);
540 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
541 flutter::DlImageSampling::kNearestNeighbor, &paint);
542 }
543
544 // Advanced blended image.
545 {
546 auto filter = flutter::DlBlendColorFilter(flutter::DlColor::kRed(),
547 flutter::DlBlendMode::kScreen);
548 paint.setColorFilter(&filter);
549 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(250, 250),
550 flutter::DlImageSampling::kNearestNeighbor, &paint);
551 }
552
553 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
554 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [237/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithColorFilterImageFilter |
| ) |  |

Definition at line 556 of file dl_unittests.cc.

556 {
557 const float invert_color_matrix[20] = {
558 -1, 0, 0, 0, 1, //
559 0, -1, 0, 0, 1, //
560 0, 0, -1, 0, 1, //
561 0, 0, 0, 1, 0, //
562 };
563 auto texture = CreateTextureForFixture("boston.jpg");
564 flutter::DisplayListBuilder builder;
565 flutter::DlPaint paint;
566
567 auto color_filter =
568 std::make_shared<flutter::DlMatrixColorFilter>(invert_color_matrix);
569 auto image_filter =
570 std::make_shared<flutter::DlColorFilterImageFilter>(color_filter);
571
572 paint.setImageFilter(image_filter.get());
573 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
574 flutter::DlImageSampling::kNearestNeighbor, &paint);
575
576 builder.Translate(0, 700);
577 paint.setColorFilter(color_filter.get());
578 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
579 flutter::DlImageSampling::kNearestNeighbor, &paint);
580 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
581 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [238/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithComposeImageFilter |
| ) |  |

Definition at line 608 of file dl_unittests.cc.

608 {
609 auto texture = CreateTextureForFixture("boston.jpg");
610 flutter::DisplayListBuilder builder;
611 flutter::DlPaint paint;
612
613 auto dilate = std::make_shared<flutter::DlDilateImageFilter>(10.0, 10.0);
614 auto erode = std::make_shared<flutter::DlErodeImageFilter>(10.0, 10.0);
615 auto open = std::make_shared<flutter::DlComposeImageFilter>(dilate, erode);
616 auto close = std::make_shared<flutter::DlComposeImageFilter>(erode, dilate);
617
618 paint.setImageFilter(open.get());
619 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
620 flutter::DlImageSampling::kNearestNeighbor, &paint);
621 builder.Translate(0, 700);
622 paint.setImageFilter(close.get());
623 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
624 flutter::DlImageSampling::kNearestNeighbor, &paint);
625 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
626 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [239/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithImageBlurFilter |
| ) |  |

Definition at line 583 of file dl_unittests.cc.

583 {
584 auto texture = CreateTextureForFixture("embarcadero.jpg");
585
586 auto callback = [&]() {
587 static float sigma[] = {10, 10};
588
589 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
590 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
591 ImGui::End();
592
593 flutter::DisplayListBuilder builder;
594 flutter::DlPaint paint;
595
596 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
597 flutter::DlTileMode::kClamp);
598 paint.setImageFilter(&filter);
599 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
600 flutter::DlImageSampling::kNearestNeighbor, &paint);
601
602 return builder.Build();
603 };
604
605 ASSERT_TRUE(OpenPlaygroundHere(callback));
606 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [240/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMaskBlur |
| ) |  |

Definition at line 442 of file dl_unittests.cc.

442 {
443 auto texture = CreateTextureForFixture("embarcadero.jpg");
444 flutter::DisplayListBuilder builder;
445 flutter::DlPaint paint;
446
447 // Mask blurred image.
448 {
449 auto filter =
450 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
451 paint.setMaskFilter(&filter);
452 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
453 flutter::DlImageSampling::kNearestNeighbor, &paint);
454 }
455
456 // Mask blurred filled path.
457 {
458 paint.setColor(flutter::DlColor::kYellow());
459 auto filter =
460 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kOuter, 10.0f);
461 paint.setMaskFilter(&filter);
462 builder.DrawArc(SkRect::MakeXYWH(410, 110, 100, 100), 45, 270, true, paint);
463 }
464
465 // Mask blurred text.
466 {
467 auto filter =
468 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kSolid, 10.0f);
469 paint.setMaskFilter(&filter);
470 builder.DrawTextBlob(
471 SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170,
472 paint);
473 }
474
475 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
476 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [241/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilter |
| ) |  |

Definition at line 1036 of file dl_unittests.cc.

1036 {
1037 auto boston = CreateTextureForFixture("boston.jpg");
1038
1039 auto callback = [&]() {
1040 static int selected_matrix_type = 0;
1041 const char* matrix_type_names[] = {"Matrix", "Local Matrix"};
1042
1043 static float ctm_translation[2] = {200, 200};
1044 static float ctm_scale[2] = {0.65, 0.65};
1045 static float ctm_skew[2] = {0, 0};
1046
1047 static bool enable = true;
1048 static float translation[2] = {100, 100};
1049 static float scale[2] = {0.8, 0.8};
1050 static float skew[2] = {0.2, 0.2};
1051
1052 static bool enable_savelayer = true;
1053
1054 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1055 {
1056 ImGui::Combo("Filter type", &selected_matrix_type, matrix_type_names,
1057 sizeof(matrix_type_names) / sizeof(char*));
1058
1059 ImGui::TextWrapped("Current Transform");
1060 ImGui::SliderFloat2("CTM Translation", ctm_translation, 0, 1000);
1061 ImGui::SliderFloat2("CTM Scale", ctm_scale, 0, 3);
1062 ImGui::SliderFloat2("CTM Skew", ctm_skew, -3, 3);
1063
1064 ImGui::TextWrapped(
1065 "MatrixFilter and LocalMatrixFilter modify the CTM in the same way. "
1066 "The only difference is that MatrixFilter doesn't affect the effect "
1067 "transform, whereas LocalMatrixFilter does.");
1068 // Note: See this behavior in:
1069 // https://fiddle.skia.org/c/6cbb551ab36d06f163db8693972be954
1070 ImGui::Checkbox("Enable", &enable);
1071 ImGui::SliderFloat2("Filter Translation", translation, 0, 1000);
1072 ImGui::SliderFloat2("Filter Scale", scale, 0, 3);
1073 ImGui::SliderFloat2("Filter Skew", skew, -3, 3);
1074
1075 ImGui::TextWrapped(
1076 "Rendering the filtered image within a layer can expose bounds "
1077 "issues. If the rendered image gets cut off when this setting is "
1078 "enabled, there's a coverage bug in the filter.");
1079 ImGui::Checkbox("Render in layer", &enable_savelayer);
1080 }
1081 ImGui::End();
1082
1083 flutter::DisplayListBuilder builder;
1084 flutter::DlPaint paint;
1085
1086 if (enable_savelayer) {
1087 builder.SaveLayer(nullptr, nullptr);
1088 }
1089 {
1090 auto content_scale = GetContentScale();
1091 builder.Scale(content_scale.x, content_scale.y);
1092
1093 // Set the current transform
1094 auto ctm_matrix =
1095 SkMatrix::MakeAll(ctm_scale[0], ctm_skew[0], ctm_translation[0], //
1096 ctm_skew[1], ctm_scale[1], ctm_translation[1], //
1097 0, 0, 1);
1098 builder.Transform(ctm_matrix);
1099
1100 // Set the matrix filter
1101 auto filter_matrix =
1102 SkMatrix::MakeAll(scale[0], skew[0], translation[0], //
1103 skew[1], scale[1], translation[1], //
1104 0, 0, 1);
1105
1106 if (enable) {
1107 switch (selected_matrix_type) {
1108 case 0: {
1109 auto filter = flutter::DlMatrixImageFilter(
1110 filter_matrix, flutter::DlImageSampling::kLinear);
1111 paint.setImageFilter(&filter);
1112 break;
1113 }
1114 case 1: {
1115 auto internal_filter =
1116 flutter::DlBlurImageFilter(10, 10, flutter::DlTileMode::kDecal)
1117 .shared();
1118 auto filter = flutter::DlLocalMatrixImageFilter(filter_matrix,
1119 internal_filter);
1120 paint.setImageFilter(&filter);
1121 break;
1122 }
1123 }
1124 }
1125
1126 builder.DrawImage(DlImageImpeller::Make(boston), {},
1127 flutter::DlImageSampling::kLinear, &paint);
1128 }
1129 if (enable_savelayer) {
1130 builder.Restore();
1131 }
1132
1133 return builder.Build();
1134 };
1135
1136 ASSERT_TRUE(OpenPlaygroundHere(callback));
1137 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [242/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilterWhenSavingLayer |
| ) |  |

Definition at line 1139 of file dl_unittests.cc.

1139 {
1140 auto callback = [&]() {
1141 static float translation[2] = {0, 0};
1142 static bool enable_save_layer = true;
1143
1144 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1145 ImGui::SliderFloat2("Translation", translation, -130, 130);
1146 ImGui::Checkbox("Enable save layer", &enable_save_layer);
1147 ImGui::End();
1148
1149 flutter::DisplayListBuilder builder;
1150 builder.Save();
1151 builder.Scale(2.0, 2.0);
1152 flutter::DlPaint paint;
1153 paint.setColor(flutter::DlColor::kYellow());
1154 builder.DrawRect(SkRect::MakeWH(300, 300), paint);
1155 paint.setStrokeWidth(1.0);
1156 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1157 paint.setColor(flutter::DlColor::kBlack().withAlpha(0x80));
1158 builder.DrawLine(SkPoint::Make(150, 0), SkPoint::Make(150, 300), paint);
1159 builder.DrawLine(SkPoint::Make(0, 150), SkPoint::Make(300, 150), paint);
1160
1161 flutter::DlPaint save_paint;
1162 SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100);
1163 SkMatrix translate_matrix =
1164 SkMatrix::Translate(translation[0], translation[1]);
1165 if (enable_save_layer) {
1166 auto filter = flutter::DlMatrixImageFilter(
1167 translate_matrix, flutter::DlImageSampling::kNearestNeighbor);
1168 save_paint.setImageFilter(filter.shared());
1169 builder.SaveLayer(&bounds, &save_paint);
1170 } else {
1171 builder.Save();
1172 builder.Transform(translate_matrix);
1173 }
1174
1175 SkMatrix filter_matrix = SkMatrix::I();
1176 filter_matrix.postTranslate(-150, -150);
1177 filter_matrix.postScale(0.2f, 0.2f);
1178 filter_matrix.postTranslate(150, 150);
1179 auto filter = flutter::DlMatrixImageFilter(
1180 filter_matrix, flutter::DlImageSampling::kNearestNeighbor);
1181
1182 save_paint.setImageFilter(filter.shared());
1183
1184 builder.SaveLayer(&bounds, &save_paint);
1185 flutter::DlPaint paint2;
1186 paint2.setColor(flutter::DlColor::kBlue());
1187 builder.DrawRect(bounds, paint2);
1188 builder.Restore();
1189 builder.Restore();
1190 return builder.Build();
1191 };
1192
1193 ASSERT_TRUE(OpenPlaygroundHere(callback));
1194 }

## ◆ TEST_P() [243/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithOddPathWinding |
| ) |  |

Definition at line 398 of file dl_unittests.cc.

398 {
399 flutter::DisplayListBuilder builder;
400 flutter::DlPaint paint;
401
402 paint.setColor(flutter::DlColor::kRed());
403 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
404
405 builder.Translate(300, 300);
406 SkPath path;
407 path.setFillType(SkPathFillType::kEvenOdd);
408 path.addCircle(0, 0, 100);
409 path.addCircle(0, 0, 50);
410 builder.DrawPath(path, paint);
411
412 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
413 }

## ◆ TEST_P() [244/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroLengthLine |
| ) |  |

Definition at line 840 of file dl_unittests.cc.

840 {
841 flutter::DisplayListBuilder builder;
842 std::vector<flutter::DlStrokeCap> caps = {
843 flutter::DlStrokeCap::kButt,
844 flutter::DlStrokeCap::kRound,
845 flutter::DlStrokeCap::kSquare,
846 };
847 flutter::DlPaint paint =
848 flutter::DlPaint() //
849 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
850 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
851 .setStrokeCap(flutter::DlStrokeCap::kButt) //
852 .setStrokeWidth(20);
853 SkPath path = SkPath().addPoly({{150, 50}, {150, 50}}, false);
854 for (auto cap : caps) {
855 paint.setStrokeCap(cap);
856 builder.DrawLine({50, 50}, {50, 50}, paint);
857 builder.DrawPath(path, paint);
858 builder.Translate(0, 150);
859 }
860 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
861 }

## ◆ TEST_P() [245/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroWidthLine |
| ) |  |

Definition at line 1002 of file dl_unittests.cc.

1002 {
1003 flutter::DisplayListBuilder builder;
1004 std::vector<flutter::DlStrokeCap> caps = {
1005 flutter::DlStrokeCap::kButt,
1006 flutter::DlStrokeCap::kRound,
1007 flutter::DlStrokeCap::kSquare,
1008 };
1009 flutter::DlPaint paint = //
1010 flutter::DlPaint() //
1011 .setColor(flutter::DlColor::kWhite()) //
1012 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1013 .setStrokeWidth(0);
1014 flutter::DlPaint outline_paint = //
1015 flutter::DlPaint() //
1016 .setColor(flutter::DlColor::kYellow()) //
1017 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1018 .setStrokeCap(flutter::DlStrokeCap::kSquare) //
1019 .setStrokeWidth(1);
1020 SkPath path = SkPath().addPoly({{150, 50}, {160, 50}}, false);
1021 for (auto cap : caps) {
1022 paint.setStrokeCap(cap);
1023 builder.DrawLine({50, 50}, {60, 50}, paint);
1024 builder.DrawRect({45, 45, 65, 55}, outline_paint);
1025 builder.DrawLine({100, 50}, {100, 50}, paint);
1026 if (cap != flutter::DlStrokeCap::kButt) {
1027 builder.DrawRect({95, 45, 105, 55}, outline_paint);
1028 }
1029 builder.DrawPath(path, paint);
1030 builder.DrawRect(path.getBounds().makeOutset(5, 5), outline_paint);
1031 builder.Translate(0, 150);
1032 }
1033 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1034 }

## ◆ TEST_P() [246/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | ClipDrawRRectWithNonCircularRadii |
| ) |  |

Definition at line 1594 of file dl_unittests.cc.

1594 {
1595 flutter::DisplayListBuilder builder;
1596
1597 flutter::DlPaint fill_paint = //
1598 flutter::DlPaint() //
1599 .setColor(flutter::DlColor::kBlue()) //
1600 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1601 .setStrokeWidth(10);
1602 flutter::DlPaint stroke_paint = //
1603 flutter::DlPaint() //
1604 .setColor(flutter::DlColor::kGreen()) //
1605 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1606 .setStrokeWidth(10);
1607
1608 builder.DrawRRect(
1609 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1610 fill_paint);
1611 builder.DrawRRect(
1612 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1613 stroke_paint);
1614
1615 builder.DrawRRect(
1616 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1617 fill_paint);
1618 builder.DrawRRect(
1619 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1620 stroke_paint);
1621
1622 flutter::DlPaint reference_paint = //
1623 flutter::DlPaint() //
1624 .setColor(flutter::DlColor::kMidGrey()) //
1625 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1626 .setStrokeWidth(10);
1627
1628 builder.DrawRRect(
1629 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 500, 300, 300), 40, 40),
1630 reference_paint);
1631 builder.DrawRRect(
1632 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 100, 300, 300), 120, 120),
1633 reference_paint);
1634
1635 flutter::DlPaint clip_fill_paint = //
1636 flutter::DlPaint() //
1637 .setColor(flutter::DlColor::kCyan()) //
1638 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1639 .setStrokeWidth(10);
1640
1641 builder.Save();
1642 builder.ClipRRect(
1643 SkRRect::MakeRectXY(SkRect::MakeXYWH(900, 100, 300, 300), 120, 40));
1644 builder.DrawPaint(clip_fill_paint);
1645 builder.Restore();
1646
1647 builder.Save();
1648 builder.ClipRRect(
1649 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 900, 300, 300), 40, 120));
1650 builder.DrawPaint(clip_fill_paint);
1651 builder.Restore();
1652
1653 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1654 }

## ◆ TEST_P() [247/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DispatcherDoesNotCullPerspectiveTransformedChildDisplayLists |
| ) |  |

Definition at line 912 of file dl_unittests.cc.

913 {
914 // Regression test for https://github.com/flutter/flutter/issues/130613
915 flutter::DisplayListBuilder sub_builder(true);
916 sub_builder.DrawRect(SkRect::MakeXYWH(0, 0, 50, 50),
917 flutter::DlPaint(flutter::DlColor::kRed()));
918 auto display_list = sub_builder.Build();
919
920 DlDispatcher dispatcher(Rect::MakeLTRB(0, 0, 2400, 1800));
921 dispatcher.scale(2.0, 2.0);
922 dispatcher.translate(-93.0, 0.0);
923 // clang-format off
924 dispatcher.transformFullPerspective(
925 0.8, -0.2, -0.1, -0.0,
926 0.0, 1.0, 0.0, 0.0,
927 1.4, 1.3, 1.0, 0.0,
928 63.2, 65.3, 48.6, 1.1
929 );
930 // clang-format on
931 dispatcher.translate(35.0, 75.0);
932 dispatcher.drawDisplayList(display_list, 1.0f);
933 auto picture = dispatcher.EndRecordingAsPicture();
934
935 bool found = false;
936 picture.pass->IterateAllEntities([&found](Entity& entity) {
937 if (std::static_pointer_cast<SolidColorContents>(entity.GetContents())
938 ->GetColor() == Color::Red()) {
939 found = true;
940 return false;
941 }
942
943 return true;
944 });
945 EXPECT_TRUE(found);
946 }

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

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawPictureWithAClip |
| ) |  |

Definition at line 49 of file dl_unittests.cc.

49 {
50 flutter::DisplayListBuilder sub_builder;
51 sub_builder.ClipRect(SkRect::MakeXYWH(0, 0, 24, 24));
52 sub_builder.DrawPaint(flutter::DlPaint(flutter::DlColor::kBlue()));
53
54 auto display_list = sub_builder.Build();
55 flutter::DisplayListBuilder builder;
56 builder.DrawDisplayList(display_list);
57 builder.DrawRect(SkRect::MakeXYWH(30, 30, 24, 24),
58 flutter::DlPaint(flutter::DlColor::kRed()));
59 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
60 }

## ◆ TEST_P() [249/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawShapes |
| ) |  |

Definition at line 1556 of file dl_unittests.cc.

1556 {
1557 flutter::DisplayListBuilder builder;
1558 std::vector<flutter::DlStrokeJoin> joins = {
1559 flutter::DlStrokeJoin::kBevel,
1560 flutter::DlStrokeJoin::kRound,
1561 flutter::DlStrokeJoin::kMiter,
1562 };
1563 flutter::DlPaint paint = //
1564 flutter::DlPaint() //
1565 .setColor(flutter::DlColor::kWhite()) //
1566 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1567 .setStrokeWidth(10);
1568 flutter::DlPaint stroke_paint = //
1569 flutter::DlPaint() //
1570 .setColor(flutter::DlColor::kWhite()) //
1571 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1572 .setStrokeWidth(10);
1573 SkPath path = SkPath().addPoly({{150, 50}, {160, 50}}, false);
1574
1575 builder.Translate(300, 50);
1576 builder.Scale(0.8, 0.8);
1577 for (auto join : joins) {
1578 paint.setStrokeJoin(join);
1579 stroke_paint.setStrokeJoin(join);
1580 builder.DrawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
1581 builder.DrawRect(SkRect::MakeXYWH(0, 150, 100, 100), stroke_paint);
1582 builder.DrawRRect(
1583 SkRRect::MakeRectXY(SkRect::MakeXYWH(150, 0, 100, 100), 30, 30), paint);
1584 builder.DrawRRect(
1585 SkRRect::MakeRectXY(SkRect::MakeXYWH(150, 150, 100, 100), 30, 30),
1586 stroke_paint);
1587 builder.DrawCircle({350, 50}, 50, paint);
1588 builder.DrawCircle({350, 200}, 50, stroke_paint);
1589 builder.Translate(0, 300);
1590 }
1591 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1592 }

## ◆ TEST_P() [250/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesBlendModes |
| ) |  |

Definition at line 1656 of file dl_unittests.cc.

1656 {
1657 std::vector<const char*> blend_mode_names;
1658 std::vector<flutter::DlBlendMode> blend_mode_values;
1659 {
1660 const std::vector<std::tuple<const char*, flutter::DlBlendMode>> blends = {
1661 // Pipeline blends (Porter-Duff alpha compositing)
1662 {"Clear", flutter::DlBlendMode::kClear},
1663 {"Source", flutter::DlBlendMode::kSrc},
1664 {"Destination", flutter::DlBlendMode::kDst},
1665 {"SourceOver", flutter::DlBlendMode::kSrcOver},
1666 {"DestinationOver", flutter::DlBlendMode::kDstOver},
1667 {"SourceIn", flutter::DlBlendMode::kSrcIn},
1668 {"DestinationIn", flutter::DlBlendMode::kDstIn},
1669 {"SourceOut", flutter::DlBlendMode::kSrcOut},
1670 {"DestinationOut", flutter::DlBlendMode::kDstOut},
1671 {"SourceATop", flutter::DlBlendMode::kSrcATop},
1672 {"DestinationATop", flutter::DlBlendMode::kDstATop},
1673 {"Xor", flutter::DlBlendMode::kXor},
1674 {"Plus", flutter::DlBlendMode::kPlus},
1675 {"Modulate", flutter::DlBlendMode::kModulate},
1676 // Advanced blends (color component blends)
1677 {"Screen", flutter::DlBlendMode::kScreen},
1678 {"Overlay", flutter::DlBlendMode::kOverlay},
1679 {"Darken", flutter::DlBlendMode::kDarken},
1680 {"Lighten", flutter::DlBlendMode::kLighten},
1681 {"ColorDodge", flutter::DlBlendMode::kColorDodge},
1682 {"ColorBurn", flutter::DlBlendMode::kColorBurn},
1683 {"HardLight", flutter::DlBlendMode::kHardLight},
1684 {"SoftLight", flutter::DlBlendMode::kSoftLight},
1685 {"Difference", flutter::DlBlendMode::kDifference},
1686 {"Exclusion", flutter::DlBlendMode::kExclusion},
1687 {"Multiply", flutter::DlBlendMode::kMultiply},
1688 {"Hue", flutter::DlBlendMode::kHue},
1689 {"Saturation", flutter::DlBlendMode::kSaturation},
1690 {"Color", flutter::DlBlendMode::kColor},
1691 {"Luminosity", flutter::DlBlendMode::kLuminosity},
1692 };
1693 assert(blends.size() ==
1694 static_cast<size_t>(flutter::DlBlendMode::kLastMode) + 1);
1695 for (const auto& [name, mode] : blends) {
1696 blend_mode_names.push_back(name);
1697 blend_mode_values.push_back(mode);
1698 }
1699 }
1700
1701 auto callback = [&]() {
1702 static int current_blend_index = 3;
1703 static float dst_alpha = 1;
1704 static float src_alpha = 1;
1705 static float color0[4] = {1.0f, 0.0f, 0.0f, 1.0f};
1706 static float color1[4] = {0.0f, 1.0f, 0.0f, 1.0f};
1707 static float color2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
1708 static float src_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
1709
1710 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1711 {
1712 ImGui::ListBox("Blending mode", &current_blend_index,
1713 blend_mode_names.data(), blend_mode_names.size());
1714 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
1715 ImGui::ColorEdit4("Color A", color0);
1716 ImGui::ColorEdit4("Color B", color1);
1717 ImGui::ColorEdit4("Color C", color2);
1718 ImGui::ColorEdit4("Source Color", src_color);
1719 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
1720 }
1721 ImGui::End();
1722
1723 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1724 SkPoint::Make(200, 100),
1725 SkPoint::Make(300, 300)};
1726 std::vector<flutter::DlColor> colors = {
1727 toColor(color0).modulateOpacity(dst_alpha),
1728 toColor(color1).modulateOpacity(dst_alpha),
1729 toColor(color2).modulateOpacity(dst_alpha)};
1730
1731 auto vertices = flutter::DlVertices::Make(
1732 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1733 /*texture_coordinates=*/nullptr, colors.data());
1734
1735 flutter::DisplayListBuilder builder;
1736 flutter::DlPaint paint;
1737
1738 paint.setColor(toColor(src_color).modulateOpacity(src_alpha));
1739 builder.DrawVertices(vertices, blend_mode_values[current_blend_index],
1740 paint);
1741 return builder.Build();
1742 };
1743
1744 ASSERT_TRUE(OpenPlaygroundHere(callback));
1745 }

References impeller::kColor, and toColor().

## ◆ TEST_P() [251/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesImageSourceWithTextureCoordinates |
| ) |  |

Definition at line 1460 of file dl_unittests.cc.

1460 {
1461 auto texture = CreateTextureForFixture("embarcadero.jpg");
1462 auto dl_image = DlImageImpeller::Make(texture);
1463 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1464 SkPoint::Make(200, 100),
1465 SkPoint::Make(300, 300)};
1466 std::vector<SkPoint> texture_coordinates = {
1467 SkPoint::Make(0, 0), SkPoint::Make(100, 200), SkPoint::Make(200, 100)};
1468
1469 auto vertices = flutter::DlVertices::Make(
1470 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1471 texture_coordinates.data(), /*colors=*/nullptr);
1472
1473 flutter::DisplayListBuilder builder;
1474 flutter::DlPaint paint;
1475
1476 auto image_source = flutter::DlImageColorSource(
1477 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
1478
1479 paint.setColorSource(&image_source);
1480 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1481
1482 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1483 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [252/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesImageSourceWithTextureCoordinatesAndColorBlending |
| ) |  |

Definition at line 1485 of file dl_unittests.cc.

1486 {
1487 auto texture = CreateTextureForFixture("embarcadero.jpg");
1488 auto dl_image = DlImageImpeller::Make(texture);
1489 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1490 SkPoint::Make(200, 100),
1491 SkPoint::Make(300, 300)};
1492 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
1493 flutter::DlColor::kGreen(),
1494 flutter::DlColor::kWhite()};
1495 std::vector<SkPoint> texture_coordinates = {
1496 SkPoint::Make(0, 0), SkPoint::Make(100, 200), SkPoint::Make(200, 100)};
1497
1498 auto vertices = flutter::DlVertices::Make(
1499 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1500 texture_coordinates.data(), colors.data());
1501
1502 flutter::DisplayListBuilder builder;
1503 flutter::DlPaint paint;
1504
1505 auto image_source = flutter::DlImageColorSource(
1506 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
1507
1508 paint.setColorSource(&image_source);
1509 builder.DrawVertices(vertices, flutter::DlBlendMode::kModulate, paint);
1510
1511 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1512 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [253/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesLinearGradientWithoutIndices |
| ) |  |

Definition at line 1405 of file dl_unittests.cc.

1405 {
1406 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1407 SkPoint::Make(200, 100),
1408 SkPoint::Make(300, 300)};
1409
1410 auto vertices = flutter::DlVertices::Make(
1411 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1412 /*texture_coordinates=*/nullptr, /*colors=*/nullptr);
1413
1414 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
1415 flutter::DlColor::kRed()};
1416 const float stops[2] = {0.0, 1.0};
1417
1418 auto linear = flutter::DlColorSource::MakeLinear(
1419 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1420 flutter::DlTileMode::kRepeat);
1421
1422 flutter::DisplayListBuilder builder;
1423 flutter::DlPaint paint;
1424
1425 paint.setColorSource(linear);
1426 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1427
1428 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1429 }

## ◆ TEST_P() [254/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesLinearGradientWithTextureCoordinates |
| ) |  |

Definition at line 1431 of file dl_unittests.cc.

1431 {
1432 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1433 SkPoint::Make(200, 100),
1434 SkPoint::Make(300, 300)};
1435 std::vector<SkPoint> texture_coordinates = {SkPoint::Make(300, 100),
1436 SkPoint::Make(100, 200),
1437 SkPoint::Make(300, 300)};
1438
1439 auto vertices = flutter::DlVertices::Make(
1440 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1441 texture_coordinates.data(), /*colors=*/nullptr);
1442
1443 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
1444 flutter::DlColor::kRed()};
1445 const float stops[2] = {0.0, 1.0};
1446
1447 auto linear = flutter::DlColorSource::MakeLinear(
1448 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1449 flutter::DlTileMode::kRepeat);
1450
1451 flutter::DisplayListBuilder builder;
1452 flutter::DlPaint paint;
1453
1454 paint.setColorSource(linear);
1455 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1456
1457 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1458 }

## ◆ TEST_P() [255/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesPremultipliesColors |
| ) |  |

Definition at line 1533 of file dl_unittests.cc.

1533 {
1534 std::vector<SkPoint> positions = {
1535 SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
1536 SkPoint::Make(200, 500)};
1537 auto color = flutter::DlColor::kBlue().withAlpha(0x99);
1538 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
1539 std::vector<flutter::DlColor> colors = {color, color, color, color};
1540
1541 auto vertices = flutter::DlVertices::Make(
1542 flutter::DlVertexMode::kTriangles, 6, positions.data(),
1543 /*texture_coordinates=*/nullptr, colors.data(), 6, indices.data());
1544
1545 flutter::DisplayListBuilder builder;
1546 flutter::DlPaint paint;
1547 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
1548 paint.setColor(flutter::DlColor::kRed());
1549
1550 builder.DrawRect(SkRect::MakeLTRB(0, 0, 400, 400), paint);
1551 builder.DrawVertices(vertices, flutter::DlBlendMode::kDst, paint);
1552
1553 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1554 }

## ◆ TEST_P() [256/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesSolidColorTrianglesWithIndices |
| ) |  |

Definition at line 1514 of file dl_unittests.cc.

1514 {
1515 std::vector<SkPoint> positions = {
1516 SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
1517 SkPoint::Make(200, 500)};
1518 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
1519
1520 auto vertices = flutter::DlVertices::Make(
1521 flutter::DlVertexMode::kTriangles, 6, positions.data(),
1522 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, 6, indices.data());
1523
1524 flutter::DisplayListBuilder builder;
1525 flutter::DlPaint paint;
1526
1527 paint.setColor(flutter::DlColor::kWhite());
1528 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1529
1530 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1531 }

## ◆ TEST_P() [257/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesSolidColorTrianglesWithoutIndices |
| ) |  |

Definition at line 1381 of file dl_unittests.cc.

1381 {
1382 // Use negative coordinates and then scale the transform by -1, -1 to make
1383 // sure coverage is taking the transform into account.
1384 std::vector<SkPoint> positions = {SkPoint::Make(-100, -300),
1385 SkPoint::Make(-200, -100),
1386 SkPoint::Make(-300, -300)};
1387 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
1388 flutter::DlColor::kGreen(),
1389 flutter::DlColor::kWhite()};
1390
1391 auto vertices = flutter::DlVertices::Make(
1392 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1393 /*texture_coordinates=*/nullptr, colors.data());
1394
1395 flutter::DisplayListBuilder builder;
1396 flutter::DlPaint paint;
1397
1398 paint.setColor(flutter::DlColor::kRed().modulateOpacity(0.5));
1399 builder.Scale(-1, -1);
1400 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1401
1402 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1403 }

## ◆ TEST_P() [258/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | IgnoreMaskFilterWhenSavingLayer |
| ) |  |

Definition at line 517 of file dl_unittests.cc.

517 {
518 auto texture = CreateTextureForFixture("embarcadero.jpg");
519 flutter::DisplayListBuilder builder;
520 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
521 flutter::DlPaint paint;
522 paint.setMaskFilter(&filter);
523 builder.SaveLayer(nullptr, &paint);
524 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
525 flutter::DlImageSampling::kNearestNeighbor);
526 builder.Restore();
527 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
528 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [259/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | MaskBlursApplyCorrectlyToColorSources |
| ) |  |

Definition at line 1344 of file dl_unittests.cc.

1344 {
1345 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
1346 flutter::DlBlurStyle::kNormal, 10);
1347
1348 flutter::DisplayListBuilder builder;
1349
1350 std::array<flutter::DlColor, 2> colors = {flutter::DlColor::kBlue(),
1351 flutter::DlColor::kGreen()};
1352 std::array<float, 2> stops = {0, 1};
1353 std::array<std::shared_ptr<flutter::DlColorSource>, 2> color_sources = {
1354 std::make_shared<flutter::DlColorColorSource>(flutter::DlColor::kWhite()),
1355 flutter::DlColorSource::MakeLinear(
1356 SkPoint::Make(0, 0), SkPoint::Make(100, 50), 2, colors.data(),
1357 stops.data(), flutter::DlTileMode::kClamp)};
1358
1359 int offset = 100;
1360 for (const auto& color_source : color_sources) {
1361 flutter::DlPaint paint;
1362 paint.setColorSource(color_source);
1363 paint.setMaskFilter(blur_filter);
1364
1365 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
1366 builder.DrawRRect(
1367 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, offset, 100, 50), 30, 30),
1368 paint);
1369 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1370 paint.setStrokeWidth(10);
1371 builder.DrawRRect(
1372 SkRRect::MakeRectXY(SkRect::MakeXYWH(300, offset, 100, 50), 30, 30),
1373 paint);
1374
1375 offset += 100;
1376 }
1377
1378 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1379 }

## ◆ TEST_P() [260/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | StrokedPathsDrawCorrectly |
| ) |  |

Definition at line 225 of file dl_unittests.cc.

225 {
226 auto callback = [&]() {
227 flutter::DisplayListBuilder builder;
228 flutter::DlPaint paint;
229
230 paint.setColor(flutter::DlColor::kRed());
231 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
232
233 static float stroke_width = 10.0f;
234 static int selected_stroke_type = 0;
235 static int selected_join_type = 0;
236 const char* stroke_types[] = {"Butte", "Round", "Square"};
237 const char* join_type[] = {"kMiter", "Round", "kBevel"};
238
239 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
240 ImGui::Combo("Cap", &selected_stroke_type, stroke_types,
241 sizeof(stroke_types) / sizeof(char*));
242 ImGui::Combo("Join", &selected_join_type, join_type,
243 sizeof(join_type) / sizeof(char*));
244 ImGui::SliderFloat("Stroke Width", &stroke_width, 10.0f, 50.0f);
245 ImGui::End();
246
247 flutter::DlStrokeCap cap;
248 flutter::DlStrokeJoin join;
249 switch (selected_stroke_type) {
250 case 0:
251 cap = flutter::DlStrokeCap::kButt;
252 break;
253 case 1:
254 cap = flutter::DlStrokeCap::kRound;
255 break;
256 case 2:
257 cap = flutter::DlStrokeCap::kSquare;
258 break;
259 default:
260 cap = flutter::DlStrokeCap::kButt;
261 break;
262 }
263 switch (selected_join_type) {
264 case 0:
265 join = flutter::DlStrokeJoin::kMiter;
266 break;
267 case 1:
268 join = flutter::DlStrokeJoin::kRound;
269 break;
270 case 2:
271 join = flutter::DlStrokeJoin::kBevel;
272 break;
273 default:
274 join = flutter::DlStrokeJoin::kMiter;
275 break;
276 }
277 paint.setStrokeCap(cap);
278 paint.setStrokeJoin(join);
279 paint.setStrokeWidth(stroke_width);
280
281 // Make rendering better to watch.
282 builder.Scale(1.5f, 1.5f);
283
284 // Rectangle
285 builder.Translate(100, 100);
286 builder.DrawRect(SkRect::MakeSize({100, 100}), paint);
287
288 // Rounded rectangle
289 builder.Translate(150, 0);
290 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10),
291 paint);
292
293 // Double rounded rectangle
294 builder.Translate(150, 0);
295 builder.DrawDRRect(
296 SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10),
297 SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 30), 10, 10), paint);
298
299 // Contour with duplicate join points
300 {
301 builder.Translate(150, 0);
302 SkPath path;
303 path.moveTo(0, 0);
304 path.lineTo(0, 0);
305 path.lineTo({100, 0});
306 path.lineTo({100, 0});
307 path.lineTo({100, 100});
308 builder.DrawPath(path, paint);
309 }
310
311 // Contour with duplicate start and end points
312
313 // Line.
314 builder.Translate(200, 0);
315 {
316 builder.Save();
317
318 SkPath line_path;
319 line_path.moveTo(0, 0);
320 line_path.moveTo(0, 0);
321 line_path.lineTo({0, 0});
322 line_path.lineTo({0, 0});
323 line_path.lineTo({50, 50});
324 line_path.lineTo({50, 50});
325 line_path.lineTo({100, 0});
326 line_path.lineTo({100, 0});
327 builder.DrawPath(line_path, paint);
328
329 builder.Translate(0, 100);
330 builder.DrawPath(line_path, paint);
331
332 builder.Translate(0, 100);
333 SkPath line_path2;
334 line_path2.moveTo(0, 0);
335 line_path2.lineTo(0, 0);
336 line_path2.lineTo(0, 0);
337 builder.DrawPath(line_path2, paint);
338
339 builder.Restore();
340 }
341
342 // Cubic.
343 builder.Translate(150, 0);
344 {
345 builder.Save();
346
347 SkPath cubic_path;
348 cubic_path.moveTo({0, 0});
349 cubic_path.cubicTo(0, 0, 140.0, 100.0, 140, 20);
350 builder.DrawPath(cubic_path, paint);
351
352 builder.Translate(0, 100);
353 SkPath cubic_path2;
354 cubic_path2.moveTo({0, 0});
355 cubic_path2.cubicTo(0, 0, 0, 0, 150, 150);
356 builder.DrawPath(cubic_path2, paint);
357
358 builder.Translate(0, 100);
359 SkPath cubic_path3;
360 cubic_path3.moveTo({0, 0});
361 cubic_path3.cubicTo(0, 0, 0, 0, 0, 0);
362 builder.DrawPath(cubic_path3, paint);
363
364 builder.Restore();
365 }
366
367 // Quad.
368 builder.Translate(200, 0);
369 {
370 builder.Save();
371
372 SkPath quad_path;
373 quad_path.moveTo(0, 0);
374 quad_path.moveTo(0, 0);
375 quad_path.quadTo({100, 40}, {50, 80});
376 builder.DrawPath(quad_path, paint);
377
378 builder.Translate(0, 150);
379 SkPath quad_path2;
380 quad_path2.moveTo(0, 0);
381 quad_path2.moveTo(0, 0);
382 quad_path2.quadTo({0, 0}, {100, 100});
383 builder.DrawPath(quad_path2, paint);
384
385 builder.Translate(0, 100);
386 SkPath quad_path3;
387 quad_path3.moveTo(0, 0);
388 quad_path3.quadTo({0, 0}, {0, 0});
389 builder.DrawPath(quad_path3, paint);
390
391 builder.Restore();
392 }
393 return builder.Build();
394 };
395 ASSERT_TRUE(OpenPlaygroundHere(callback));
396 }

## ◆ TEST_P() [261/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | StrokedTextNotOffsetFromNormalText |
| ) |  |

Definition at line 492 of file dl_unittests.cc.

492 {
493 flutter::DisplayListBuilder builder;
494 flutter::DlPaint paint;
495 auto const& text_blob = SkTextBlob::MakeFromString("00000", CreateTestFont());
496
497 // https://api.flutter.dev/flutter/material/Colors/blue-constant.html.
498 auto const& mat_blue = flutter::DlColor(0xFF2196f3);
499
500 // Draw a blue filled rectangle so the text is easier to see.
501 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
502 paint.setColor(mat_blue);
503 builder.DrawRect(SkRect::MakeXYWH(0, 0, 500, 500), paint);
504
505 // Draw stacked text, with stroked text on top.
506 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
507 paint.setColor(flutter::DlColor::kWhite());
508 builder.DrawTextBlob(text_blob, 250, 250, paint);
509
510 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
511 paint.setColor(flutter::DlColor::kBlack());
512 builder.DrawTextBlob(text_blob, 250, 250, paint);
513
514 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
515 }

## ◆ TEST_P() [262/384]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | TransparentShadowProducesCorrectColor |
| ) |  |

Definition at line 948 of file dl_unittests.cc.

948 {
949 DlDispatcher dispatcher;
950 dispatcher.save();
951 dispatcher.scale(1.618, 1.618);
952 dispatcher.drawShadow(SkPath{}.addRect(SkRect::MakeXYWH(0, 0, 200, 100)),
953 flutter::DlColor::kTransparent(), 15, false, 1);
954 dispatcher.restore();
955 auto picture = dispatcher.EndRecordingAsPicture();
956
957 std::shared_ptr<SolidRRectBlurContents> rrect_blur;
958 picture.pass->IterateAllEntities([&rrect_blur](Entity& entity) {
959 if (ScalarNearlyEqual(entity.GetTransform().GetScale().x, 1.618f)) {
960 rrect_blur = std::static_pointer_cast<SolidRRectBlurContents>(
961 entity.GetContents());
962 return false;
963 }
964 return true;
965 });
966
967 ASSERT_NE(rrect_blur, nullptr);
968 ASSERT_EQ(rrect_blur->GetColor().red, 0);
969 ASSERT_EQ(rrect_blur->GetColor().green, 0);
970 ASSERT_EQ(rrect_blur->GetColor().blue, 0);
971 ASSERT_EQ(rrect_blur->GetColor().alpha, 0);
972 }

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

impeller::testing::TEST_P | ( | EntityPassTargetTest | ,
|  | SwapWithMSAAImplicitResolve |
| ) |  |

Definition at line 52 of file entity_pass_target_unittests.cc.

52 {
53 auto content_context = GetContentContext();
54 auto buffer = content_context->GetContext()->CreateCommandBuffer();
55 auto context = content_context->GetContext();
56 auto& allocator = *context->GetResourceAllocator();
57
58 // Emulate implicit MSAA resolve by making color resolve and msaa texture the
59 // same.
60 RenderTarget render_target;
61 {
62 PixelFormat pixel_format =
63 context->GetCapabilities()->GetDefaultColorFormat();
64
65 // Create MSAA color texture.
66
67 TextureDescriptor color0_tex_desc;
68 color0_tex_desc.storage_mode = StorageMode::kDevicePrivate;
69 color0_tex_desc.type = TextureType::kTexture2DMultisample;
70 color0_tex_desc.sample_count = SampleCount::kCount4;
71 color0_tex_desc.format = pixel_format;
72 color0_tex_desc.size = ISize{100, 100};
73 color0_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget);
74
75 auto color0_msaa_tex = allocator.CreateTexture(color0_tex_desc);
76
77 // Color attachment.
78
79 ColorAttachment color0;
80 color0.load_action = LoadAction::kDontCare;
81 color0.store_action = StoreAction::kStoreAndMultisampleResolve;
82 color0.texture = color0_msaa_tex;
83 color0.resolve_texture = color0_msaa_tex;
84
85 render_target.SetColorAttachment(color0, 0u);
86 render_target.SetStencilAttachment(std::nullopt);
87 }
88
89 auto entity_pass_target = EntityPassTarget(render_target, false, true);
90
91 auto color0 = entity_pass_target.GetRenderTarget()
92 .GetColorAttachments()
93 .find(0u)
94 ->second;
95 auto msaa_tex = color0.texture;
96 auto resolve_tex = color0.resolve_texture;
97
98 ASSERT_EQ(msaa_tex, resolve_tex);
99
100 entity_pass_target.Flip(
101 *content_context->GetContext()->GetResourceAllocator());
102
103 color0 = entity_pass_target.GetRenderTarget()
104 .GetColorAttachments()
105 .find(0u)
106 ->second;
107
108 ASSERT_NE(msaa_tex, color0.texture);
109 ASSERT_NE(resolve_tex, color0.resolve_texture);
110 ASSERT_EQ(color0.texture, color0.resolve_texture);
111 }

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

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 = RenderTarget::CreateOffscreenMSAA(
28 *content_context->GetContext(),
29 *GetContentContext()->GetRenderTargetCache(), {100, 100});
30
31 auto entity_pass_target = EntityPassTarget(render_target, false, false);
32
33 auto color0 = entity_pass_target.GetRenderTarget()
34 .GetColorAttachments()
35 .find(0u)
36 ->second;
37 auto msaa_tex = color0.texture;
38 auto resolve_tex = color0.resolve_texture;
39
40 entity_pass_target.Flip(
41 *content_context->GetContext()->GetResourceAllocator());
42
43 color0 = entity_pass_target.GetRenderTarget()
44 .GetColorAttachments()
45 .find(0u)
46 ->second;
47
48 ASSERT_EQ(msaa_tex, color0.texture);
49 ASSERT_NE(resolve_tex, color0.resolve_texture);
50 }

References impeller::RenderTarget::CreateOffscreenMSAA().

## ◆ TEST_P() [265/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | AdvancedBlendCoverageHintIsNotResetByEntityPass |
| ) |  |

Definition at line 2484 of file entity_unittests.cc.

2484 {
2485 if (GetContext()->GetCapabilities()->SupportsFramebufferFetch()) {
2486 GTEST_SKIP() << "Backends that support framebuffer fetch dont use coverage "
2487 "for advanced blends.";
2488 }
2489
2490 auto contents = std::make_shared<SolidColorContents>();
2491 contents->SetGeometry(Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100)));
2492 contents->SetColor(Color::Red());
2493
2494 Entity entity;
2495 entity.SetTransform(Matrix::MakeScale(Vector3(2, 2, 1)));
2496 entity.SetBlendMode(BlendMode::kColorBurn);
2497 entity.SetContents(contents);
2498
2499 auto coverage = entity.GetCoverage();
2500 EXPECT_TRUE(coverage.has_value());
2501
2502 auto pass = std::make_unique<EntityPass>();
2503 auto test_allocator = std::make_shared<TestRenderTargetAllocator>(
2504 GetContext()->GetResourceAllocator());
2505 auto stencil_config = RenderTarget::AttachmentConfig{
2506 .storage_mode = StorageMode::kDevicePrivate,
2507 .load_action = LoadAction::kClear,
2508 .store_action = StoreAction::kDontCare,
2509 .clear_color = Color::BlackTransparent()};
2510 auto rt = RenderTarget::CreateOffscreen(
2511 *GetContext(), *test_allocator, ISize::MakeWH(1000, 1000), "Offscreen",
2512 RenderTarget::kDefaultColorAttachmentConfig, stencil_config);
2513 auto content_context = ContentContext(
2514 GetContext(), TypographerContextSkia::Make(), test_allocator);
2515 pass->AddEntity(std::move(entity));
2516
2517 EXPECT_TRUE(pass->Render(content_context, rt));
2518
2519 if (test_allocator->GetDescriptors().size() == 6u) {
2520 EXPECT_EQ(test_allocator->GetDescriptors()[0].size, ISize(1000, 1000));
2521 EXPECT_EQ(test_allocator->GetDescriptors()[1].size, ISize(1000, 1000));
2522
2523 EXPECT_EQ(test_allocator->GetDescriptors()[2].size, ISize(200, 200));
2524 EXPECT_EQ(test_allocator->GetDescriptors()[3].size, ISize(200, 200));
2525 EXPECT_EQ(test_allocator->GetDescriptors()[4].size, ISize(200, 200));
2526 EXPECT_EQ(test_allocator->GetDescriptors()[5].size, ISize(200, 200));
2527 } else if (test_allocator->GetDescriptors().size() == 9u) {
2528 // Onscreen render target.
2529 EXPECT_EQ(test_allocator->GetDescriptors()[0].size, ISize(1000, 1000));
2530 EXPECT_EQ(test_allocator->GetDescriptors()[1].size, ISize(1000, 1000));
2531 EXPECT_EQ(test_allocator->GetDescriptors()[2].size, ISize(1000, 1000));
2532 EXPECT_EQ(test_allocator->GetDescriptors()[3].size, ISize(1000, 1000));
2533 EXPECT_EQ(test_allocator->GetDescriptors()[4].size, ISize(1000, 1000));
2534
2535 EXPECT_EQ(test_allocator->GetDescriptors()[5].size, ISize(200, 200));
2536 EXPECT_EQ(test_allocator->GetDescriptors()[5].size, ISize(200, 200));
2537 EXPECT_EQ(test_allocator->GetDescriptors()[6].size, ISize(200, 200));
2538 EXPECT_EQ(test_allocator->GetDescriptors()[7].size, ISize(200, 200));
2539 } else {
2540 EXPECT_TRUE(false);
2541 }
2542 }

References impeller::Color::BlackTransparent(), impeller::RenderTarget::CreateOffscreen(), 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() [266/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | AtlasContentsSubAtlas |
| ) |  |

Definition at line 1970 of file entity_unittests.cc.

1970 {
1971 auto boston = CreateTextureForFixture("boston.jpg");
1972
1973 {
1974 auto contents = std::make_shared<AtlasContents>();
1975 contents->SetBlendMode(BlendMode::kSourceOver);
1976 contents->SetTexture(boston);
1977 contents->SetColors({
1978 Color::Red(),
1979 Color::Red(),
1980 Color::Red(),
1981 });
1982 contents->SetTextureCoordinates({
1983 Rect::MakeLTRB(0, 0, 10, 10),
1984 Rect::MakeLTRB(0, 0, 10, 10),
1985 Rect::MakeLTRB(0, 0, 10, 10),
1986 });
1987 contents->SetTransforms({
1988 Matrix::MakeTranslation(Vector2(0, 0)),
1989 Matrix::MakeTranslation(Vector2(100, 100)),
1990 Matrix::MakeTranslation(Vector2(200, 200)),
1991 });
1992
1993 // Since all colors and sample rects are the same, there should
1994 // only be a single entry in the sub atlas.
1995 auto subatlas = contents->GenerateSubAtlas();
1996 ASSERT_EQ(subatlas->sub_texture_coords.size(), 1u);
1997 }
1998
1999 {
2000 auto contents = std::make_shared<AtlasContents>();
2001 contents->SetBlendMode(BlendMode::kSourceOver);
2002 contents->SetTexture(boston);
2003 contents->SetColors({
2004 Color::Red(),
2005 Color::Green(),
2006 Color::Blue(),
2007 });
2008 contents->SetTextureCoordinates({
2009 Rect::MakeLTRB(0, 0, 10, 10),
2010 Rect::MakeLTRB(0, 0, 10, 10),
2011 Rect::MakeLTRB(0, 0, 10, 10),
2012 });
2013 contents->SetTransforms({
2014 Matrix::MakeTranslation(Vector2(0, 0)),
2015 Matrix::MakeTranslation(Vector2(100, 100)),
2016 Matrix::MakeTranslation(Vector2(200, 200)),
2017 });
2018
2019 // Since all colors are different, there are three entires.
2020 auto subatlas = contents->GenerateSubAtlas();
2021 ASSERT_EQ(subatlas->sub_texture_coords.size(), 3u);
2022
2023 // The translations are kept but the sample rects point into
2024 // different parts of the sub atlas.
2025 ASSERT_EQ(subatlas->result_texture_coords[0], Rect::MakeXYWH(0, 0, 10, 10));
2026 ASSERT_EQ(subatlas->result_texture_coords[1],
2027 Rect::MakeXYWH(11, 0, 10, 10));
2028 ASSERT_EQ(subatlas->result_texture_coords[2],
2029 Rect::MakeXYWH(22, 0, 10, 10));
2030 }
2031 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BezierCircleScaled |
| ) |  |

Definition at line 926 of file entity_unittests.cc.

926 {
927 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
928 static float scale = 20;
929
930 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
931 ImGui::SliderFloat("Scale", &scale, 1, 100);
932 ImGui::End();
933
934 Entity entity;
935 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
936 auto path = PathBuilder{}
937 .MoveTo({97.325, 34.818})
938 .CubicCurveTo({98.50862885295136, 34.81812293973836},
939 {99.46822048142015, 33.85863261475589},
940 {99.46822048142015, 32.67499810206613})
941 .CubicCurveTo({99.46822048142015, 31.491363589376355},
942 {98.50862885295136, 30.53187326439389},
943 {97.32499434685802, 30.531998226542708})
944 .CubicCurveTo({96.14153655073771, 30.532123170035373},
945 {95.18222070648729, 31.491540299350355},
946 {95.18222070648729, 32.67499810206613})
947 .CubicCurveTo({95.18222070648729, 33.85845590478189},
948 {96.14153655073771, 34.81787303409686},
949 {97.32499434685802, 34.81799797758954})
950 .Close()
951 .TakePath();
952 entity.SetTransform(
953 Matrix::MakeScale({scale, scale, 1.0}).Translate({-90, -20, 0}));
954 entity.SetContents(SolidColorContents::Make(std::move(path), Color::Red()));
955 return entity.Render(context, pass);
956 };
957 ASSERT_TRUE(OpenPlaygroundHere(callback));
958 }

References impeller::Close(), impeller::SolidColorContents::Make(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [268/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BlendingModeOptions |
| ) |  |

Definition at line 799 of file entity_unittests.cc.

799 {
800 std::vector<const char*> blend_mode_names;
801 std::vector<BlendMode> blend_mode_values;
802 {
803 // Force an exhausiveness check with a switch. When adding blend modes,
804 // update this switch with a new name/value to make it selectable in the
805 // test GUI.
806
807 const BlendMode b{};
808 static_assert(b == BlendMode::kClear); // Ensure the first item in
809 // the switch is the first
810 // item in the enum.
811 static_assert(Entity::kLastPipelineBlendMode == BlendMode::kModulate);
812 switch (b) {
813 case BlendMode::kClear:
814 blend_mode_names.push_back("Clear");
815 blend_mode_values.push_back(BlendMode::kClear);
816 case BlendMode::kSource:
817 blend_mode_names.push_back("Source");
818 blend_mode_values.push_back(BlendMode::kSource);
819 case BlendMode::kDestination:
820 blend_mode_names.push_back("Destination");
821 blend_mode_values.push_back(BlendMode::kDestination);
822 case BlendMode::kSourceOver:
823 blend_mode_names.push_back("SourceOver");
824 blend_mode_values.push_back(BlendMode::kSourceOver);
825 case BlendMode::kDestinationOver:
826 blend_mode_names.push_back("DestinationOver");
827 blend_mode_values.push_back(BlendMode::kDestinationOver);
828 case BlendMode::kSourceIn:
829 blend_mode_names.push_back("SourceIn");
830 blend_mode_values.push_back(BlendMode::kSourceIn);
831 case BlendMode::kDestinationIn:
832 blend_mode_names.push_back("DestinationIn");
833 blend_mode_values.push_back(BlendMode::kDestinationIn);
834 case BlendMode::kSourceOut:
835 blend_mode_names.push_back("SourceOut");
836 blend_mode_values.push_back(BlendMode::kSourceOut);
837 case BlendMode::kDestinationOut:
838 blend_mode_names.push_back("DestinationOut");
839 blend_mode_values.push_back(BlendMode::kDestinationOut);
840 case BlendMode::kSourceATop:
841 blend_mode_names.push_back("SourceATop");
842 blend_mode_values.push_back(BlendMode::kSourceATop);
843 case BlendMode::kDestinationATop:
844 blend_mode_names.push_back("DestinationATop");
845 blend_mode_values.push_back(BlendMode::kDestinationATop);
846 case BlendMode::kXor:
847 blend_mode_names.push_back("Xor");
848 blend_mode_values.push_back(BlendMode::kXor);
849 case BlendMode::kPlus:
850 blend_mode_names.push_back("Plus");
851 blend_mode_values.push_back(BlendMode::kPlus);
852 case BlendMode::kModulate:
853 blend_mode_names.push_back("Modulate");
854 blend_mode_values.push_back(BlendMode::kModulate);
855 };
856 }
857
858 auto callback = [&](ContentContext& context, RenderPass& pass) {
859 auto world_matrix = Matrix::MakeScale(GetContentScale());
860 auto draw_rect = [&context, &pass, &world_matrix](
861 Rect rect, Color color, BlendMode blend_mode) -> bool {
862 using VS = SolidFillPipeline::VertexShader;
863
864 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
865 {
866 auto r = rect.GetLTRB();
867 vtx_builder.AddVertices({
868 {Point(r[0], r[1])},
869 {Point(r[2], r[1])},
870 {Point(r[2], r[3])},
871 {Point(r[0], r[1])},
872 {Point(r[2], r[3])},
873 {Point(r[0], r[3])},
874 });
875 }
876
877 Command cmd;
878 DEBUG_COMMAND_INFO(cmd, "Blended Rectangle");
879 auto options = OptionsFromPass(pass);
880 options.blend_mode = blend_mode;
881 options.primitive_type = PrimitiveType::kTriangle;
882 cmd.pipeline = context.GetSolidFillPipeline(options);
883 cmd.BindVertices(
884 vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer()));
885
886 VS::FrameInfo frame_info;
887 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
888 frame_info.color = color.Premultiply();
889 VS::BindFrameInfo(cmd,
890 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
891
892 return pass.AddCommand(std::move(cmd));
893 };
894
895 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
896 static Color color1(1, 0, 0, 0.5), color2(0, 1, 0, 0.5);
897 ImGui::ColorEdit4("Color 1", reinterpret_cast<float*>(&color1));
898 ImGui::ColorEdit4("Color 2", reinterpret_cast<float*>(&color2));
899 static int current_blend_index = 3;
900 ImGui::ListBox("Blending mode", &current_blend_index,
901 blend_mode_names.data(), blend_mode_names.size());
902 ImGui::End();
903
904 BlendMode selected_mode = blend_mode_values[current_blend_index];
905
906 Point a, b, c, d;
907 std::tie(a, b) = IMPELLER_PLAYGROUND_LINE(
908 Point(400, 100), Point(200, 300), 20, Color::White(), Color::White());
909 std::tie(c, d) = IMPELLER_PLAYGROUND_LINE(
910 Point(470, 190), Point(270, 390), 20, Color::White(), Color::White());
911
912 bool result = true;
913 result = result &&
914 draw_rect(Rect::MakeXYWH(0, 0, pass.GetRenderTargetSize().width,
915 pass.GetRenderTargetSize().height),
916 Color(), BlendMode::kClear);
917 result = result && draw_rect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), color1,
918 BlendMode::kSourceOver);
919 result = result && draw_rect(Rect::MakeLTRB(c.x, c.y, d.x, d.y), color2,
920 selected_mode);
921 return result;
922 };
923 ASSERT_TRUE(OpenPlaygroundHere(callback));
924 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::ContentContext::GetSolidFillPipeline(), IMPELLER_PLAYGROUND_LINE, 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::Command::pipeline, impeller::Color::White(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [269/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BorderMaskBlurCoverageIsCorrect |
| ) |  |

Definition at line 1333 of file entity_unittests.cc.

1333 {
1334 auto fill = std::make_shared<SolidColorContents>();
1335 fill->SetGeometry(Geometry::MakeFillPath(
1336 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1337 fill->SetColor(Color::CornflowerBlue());
1338 auto border_mask_blur = FilterContents::MakeBorderMaskBlur(
1339 FilterInput::Make(fill), Radius{3}, Radius{4});
1340
1341 {
1342 Entity e;
1343 e.SetTransform(Matrix());
1344 auto actual = border_mask_blur->GetCoverage(e);
1345 auto expected = Rect::MakeXYWH(-3, -4, 306, 408);
1346 ASSERT_TRUE(actual.has_value());
1347 ASSERT_RECT_NEAR(actual.value(), expected);
1348 }
1349
1350 {
1351 Entity e;
1352 e.SetTransform(Matrix::MakeRotationZ(Radians{kPi / 4}));
1353 auto actual = border_mask_blur->GetCoverage(e);
1354 auto expected = Rect::MakeXYWH(-287.792, -4.94975, 504.874, 504.874);
1355 ASSERT_TRUE(actual.has_value());
1356 ASSERT_RECT_NEAR(actual.value(), expected);
1357 }
1358 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanCreateEntity |
| ) |  |

Definition at line 66 of file entity_unittests.cc.

66 {
67 Entity entity;
68 ASSERT_TRUE(entity.GetTransform().IsIdentity());
69 }

References impeller::Entity::GetTransform(), and impeller::Matrix::IsIdentity().

## ◆ TEST_P() [271/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawCorrectlyWithRotatedTransform |
| ) |  |

Definition at line 483 of file entity_unittests.cc.

483 {
484 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
485 const char* input_axis[] = {"X", "Y", "Z"};
486 static int rotation_axis_index = 0;
487 static float rotation = 0;
488 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
489 ImGui::SliderFloat("Rotation", &rotation, -kPi, kPi);
490 ImGui::Combo("Rotation Axis", &rotation_axis_index, input_axis,
491 sizeof(input_axis) / sizeof(char*));
492 Matrix rotation_matrix;
493 switch (rotation_axis_index) {
494 case 0:
495 rotation_matrix = Matrix::MakeRotationX(Radians(rotation));
496 break;
497 case 1:
498 rotation_matrix = Matrix::MakeRotationY(Radians(rotation));
499 break;
500 case 2:
501 rotation_matrix = Matrix::MakeRotationZ(Radians(rotation));
502 break;
503 default:
504 rotation_matrix = Matrix{};
505 break;
506 }
507
508 if (ImGui::Button("Reset")) {
509 rotation = 0;
510 }
511 ImGui::End();
512 Matrix current_transform =
513 Matrix::MakeScale(GetContentScale())
514 .MakeTranslation(
515 Vector3(Point(pass.GetRenderTargetSize().width / 2.0,
516 pass.GetRenderTargetSize().height / 2.0)));
517 Matrix result_transform = current_transform * rotation_matrix;
518 Path path =
519 PathBuilder{}.AddRect(Rect::MakeXYWH(-300, -400, 600, 800)).TakePath();
520
521 Entity entity;
522 entity.SetTransform(result_transform);
523 entity.SetContents(SolidColorContents::Make(std::move(path), Color::Red()));
524 return entity.Render(context, pass);
525 };
526 ASSERT_TRUE(OpenPlaygroundHere(callback));
527 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawRect |
| ) |  |

Definition at line 221 of file entity_unittests.cc.

221 {
222 auto contents = std::make_shared<SolidColorContents>();
223 contents->SetGeometry(Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100)));
224 contents->SetColor(Color::Red());
225
226 Entity entity;
227 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
228 entity.SetContents(contents);
229
230 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
231 }

References impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [273/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawRRect |
| ) |  |

Definition at line 233 of file entity_unittests.cc.

233 {
234 auto contents = std::make_shared<SolidColorContents>();
235 auto path = PathBuilder{}
236 .SetConvexity(Convexity::kConvex)
237 .AddRoundedRect(Rect::MakeXYWH(100, 100, 100, 100), 10.0)
238 .TakePath();
239 contents->SetGeometry(Geometry::MakeFillPath(std::move(path)));
240 contents->SetColor(Color::Red());
241
242 Entity entity;
243 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
244 entity.SetContents(contents);
245
246 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
247 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ClipContentsGetClipCoverageIsCorrect |
| ) |  |

Definition at line 1669 of file entity_unittests.cc.

1669 {
1670 // Intersection: No stencil coverage, no geometry.
1671 {
1672 auto clip = std::make_shared<ClipContents>();
1673 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1674 auto result = clip->GetClipCoverage(Entity{}, Rect{});
1675
1676 ASSERT_FALSE(result.coverage.has_value());
1677 }
1678
1679 // Intersection: No stencil coverage, with geometry.
1680 {
1681 auto clip = std::make_shared<ClipContents>();
1682 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1683 clip->SetGeometry(Geometry::MakeFillPath(
1684 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1685 auto result = clip->GetClipCoverage(Entity{}, Rect{});
1686
1687 ASSERT_FALSE(result.coverage.has_value());
1688 }
1689
1690 // Intersection: With stencil coverage, no geometry.
1691 {
1692 auto clip = std::make_shared<ClipContents>();
1693 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1694 auto result =
1695 clip->GetClipCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1696
1697 ASSERT_FALSE(result.coverage.has_value());
1698 }
1699
1700 // Intersection: With stencil coverage, with geometry.
1701 {
1702 auto clip = std::make_shared<ClipContents>();
1703 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1704 clip->SetGeometry(Geometry::MakeFillPath(
1705 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 50, 50)).TakePath()));
1706 auto result =
1707 clip->GetClipCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1708
1709 ASSERT_TRUE(result.coverage.has_value());
1710 ASSERT_RECT_NEAR(result.coverage.value(), Rect::MakeLTRB(0, 0, 50, 50));
1711 ASSERT_EQ(result.type, Contents::ClipCoverage::Type::kAppend);
1712 }
1713
1714 // Difference: With stencil coverage, with geometry.
1715 {
1716 auto clip = std::make_shared<ClipContents>();
1717 clip->SetClipOperation(Entity::ClipOperation::kDifference);
1718 clip->SetGeometry(Geometry::MakeFillPath(
1719 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 50, 50)).TakePath()));
1720 auto result =
1721 clip->GetClipCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1722
1723 ASSERT_TRUE(result.coverage.has_value());
1724 ASSERT_RECT_NEAR(result.coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
1725 ASSERT_EQ(result.type, Contents::ClipCoverage::Type::kAppend);
1726 }
1727 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ClipContentsShouldRenderIsCorrect |
| ) |  |

Definition at line 1645 of file entity_unittests.cc.

1645 {
1646 // For clip ops, `ShouldRender` should always return true.
1647
1648 // Clip.
1649 {
1650 auto clip = std::make_shared<ClipContents>();
1651 ASSERT_TRUE(clip->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1652 clip->SetGeometry(Geometry::MakeFillPath(
1653 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1654 ASSERT_TRUE(clip->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1655 ASSERT_TRUE(
1656 clip->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1657 }
1658
1659 // Clip restore.
1660 {
1661 auto restore = std::make_shared<ClipRestoreContents>();
1662 ASSERT_TRUE(
1663 restore->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1664 ASSERT_TRUE(
1665 restore->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1666 }
1667 }

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

## ◆ TEST_P() [276/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterContentsWithLargeGeometry |
| ) |  |

Definition at line 2434 of file entity_unittests.cc.

2434 {
2435 Entity entity;
2436 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2437 auto src_contents = std::make_shared<SolidColorContents>();
2438 src_contents->SetGeometry(
2439 Geometry::MakeRect(Rect::MakeLTRB(-300, -500, 30000, 50000)));
2440 src_contents->SetColor(Color::Red());
2441
2442 auto dst_contents = std::make_shared<SolidColorContents>();
2443 dst_contents->SetGeometry(
2444 Geometry::MakeRect(Rect::MakeLTRB(300, 500, 20000, 30000)));
2445 dst_contents->SetColor(Color::Blue());
2446
2447 auto contents = ColorFilterContents::MakeBlend(
2448 BlendMode::kSourceOver, {FilterInput::Make(dst_contents, false),
2449 FilterInput::Make(src_contents, false)});
2450 entity.SetContents(std::move(contents));
2451 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2452 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorAdvancedBlend |
| ) |  |

Definition at line 2248 of file entity_unittests.cc.

2248 {
2249 auto image = CreateTextureForFixture("boston.jpg");
2250 auto filter = ColorFilterContents::MakeBlend(
2251 BlendMode::kColorBurn, FilterInput::Make({image}), Color::Red());
2252
2253 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2254 Entity entity;
2255 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2256 Matrix::MakeTranslation({500, 300}) *
2257 Matrix::MakeScale(Vector2{0.5, 0.5}));
2258 entity.SetContents(filter);
2259 return entity.Render(context, pass);
2260 };
2261 ASSERT_TRUE(OpenPlaygroundHere(callback));
2262 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorClearBlend |
| ) |  |

Definition at line 2264 of file entity_unittests.cc.

2264 {
2265 auto image = CreateTextureForFixture("boston.jpg");
2266 auto filter = ColorFilterContents::MakeBlend(
2267 BlendMode::kClear, FilterInput::Make({image}), Color::Red());
2268
2269 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2270 Entity entity;
2271 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2272 Matrix::MakeTranslation({500, 300}) *
2273 Matrix::MakeScale(Vector2{0.5, 0.5}));
2274 entity.SetContents(filter);
2275 return entity.Render(context, pass);
2276 };
2277 ASSERT_TRUE(OpenPlaygroundHere(callback));
2278 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorDstBlend |
| ) |  |

Definition at line 2296 of file entity_unittests.cc.

2296 {
2297 auto image = CreateTextureForFixture("boston.jpg");
2298 auto filter = ColorFilterContents::MakeBlend(
2299 BlendMode::kDestination, FilterInput::Make({image}), Color::Red());
2300
2301 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2302 Entity entity;
2303 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2304 Matrix::MakeTranslation({500, 300}) *
2305 Matrix::MakeScale(Vector2{0.5, 0.5}));
2306 entity.SetContents(filter);
2307 return entity.Render(context, pass);
2308 };
2309 ASSERT_TRUE(OpenPlaygroundHere(callback));
2310 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcBlend |
| ) |  |

Definition at line 2280 of file entity_unittests.cc.

2280 {
2281 auto image = CreateTextureForFixture("boston.jpg");
2282 auto filter = ColorFilterContents::MakeBlend(
2283 BlendMode::kSource, FilterInput::Make({image}), Color::Red());
2284
2285 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2286 Entity entity;
2287 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2288 Matrix::MakeTranslation({500, 300}) *
2289 Matrix::MakeScale(Vector2{0.5, 0.5}));
2290 entity.SetContents(filter);
2291 return entity.Render(context, pass);
2292 };
2293 ASSERT_TRUE(OpenPlaygroundHere(callback));
2294 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcInBlend |
| ) |  |

Definition at line 2312 of file entity_unittests.cc.

2312 {
2313 auto image = CreateTextureForFixture("boston.jpg");
2314 auto filter = ColorFilterContents::MakeBlend(
2315 BlendMode::kSourceIn, FilterInput::Make({image}), Color::Red());
2316
2317 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2318 Entity entity;
2319 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2320 Matrix::MakeTranslation({500, 300}) *
2321 Matrix::MakeScale(Vector2{0.5, 0.5}));
2322 entity.SetContents(filter);
2323 return entity.Render(context, pass);
2324 };
2325 ASSERT_TRUE(OpenPlaygroundHere(callback));
2326 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterCoverageIsCorrect |
| ) |  |

Definition at line 1779 of file entity_unittests.cc.

1779 {
1780 // Set up a simple color background.
1781 auto fill = std::make_shared<SolidColorContents>();
1782 fill->SetGeometry(Geometry::MakeFillPath(
1783 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1784 fill->SetColor(Color::Coral());
1785
1786 // Set the color matrix filter.
1787 ColorMatrix matrix = {
1788 1, 1, 1, 1, 1, //
1789 1, 1, 1, 1, 1, //
1790 1, 1, 1, 1, 1, //
1791 1, 1, 1, 1, 1, //
1792 };
1793
1794 auto filter =
1795 ColorFilterContents::MakeColorMatrix(FilterInput::Make(fill), matrix);
1796
1797 Entity e;
1798 e.SetTransform(Matrix());
1799
1800 // Confirm that the actual filter coverage matches the expected coverage.
1801 auto actual = filter->GetCoverage(e);
1802 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1803
1804 ASSERT_TRUE(actual.has_value());
1805 ASSERT_RECT_NEAR(actual.value(), expected);
1806 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterEditable |
| ) |  |

Definition at line 1808 of file entity_unittests.cc.

1808 {
1809 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
1810 ASSERT_TRUE(bay_bridge);
1811
1812 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1813 // UI state.
1814 static ColorMatrix color_matrix = {
1815 1, 0, 0, 0, 0, //
1816 0, 3, 0, 0, 0, //
1817 0, 0, 1, 0, 0, //
1818 0, 0, 0, 1, 0, //
1819 };
1820 static float offset[2] = {500, 400};
1821 static float rotation = 0;
1822 static float scale[2] = {0.65, 0.65};
1823 static float skew[2] = {0, 0};
1824
1825 // Define the ImGui
1826 ImGui::Begin("Color Matrix", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1827 {
1828 std::string label = "##1";
1829 for (int i = 0; i < 20; i += 5) {
1830 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
1831 &(color_matrix.array[i]), 5, nullptr, nullptr,
1832 "%.2f", 0);
1833 label[2]++;
1834 }
1835
1836 ImGui::SliderFloat2("Translation", &offset[0], 0,
1837 pass.GetRenderTargetSize().width);
1838 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1839 ImGui::SliderFloat2("Scale", &scale[0], 0, 3);
1840 ImGui::SliderFloat2("Skew", &skew[0], -3, 3);
1841 }
1842 ImGui::End();
1843
1844 // Set the color matrix filter.
1845 auto filter = ColorFilterContents::MakeColorMatrix(
1846 FilterInput::Make(bay_bridge), color_matrix);
1847
1848 // Define the entity with the color matrix filter.
1849 Entity entity;
1850 entity.SetTransform(
1851 Matrix::MakeScale(GetContentScale()) *
1852 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1853 Matrix::MakeRotationZ(Radians(rotation)) *
1854 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1855 Matrix::MakeSkew(skew[0], skew[1]) *
1856 Matrix::MakeTranslation(-Point(bay_bridge->GetSize()) / 2));
1857 entity.SetContents(filter);
1858 entity.Render(context, pass);
1859
1860 return true;
1861 };
1862
1863 ASSERT_TRUE(OpenPlaygroundHere(callback));
1864 }

References impeller::ColorMatrix::array, impeller::kPi, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeColorMatrix(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeSkew(), impeller::Matrix::MakeTranslation(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [284/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ConicalGradientContentsIsOpaque |
| ) |  |

Definition at line 2352 of file entity_unittests.cc.

2352 {
2353 ConicalGradientContents contents;
2354 contents.SetColors({Color::CornflowerBlue()});
2355 ASSERT_FALSE(contents.IsOpaque());
2356 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2357 ASSERT_FALSE(contents.IsOpaque());
2358 }

References impeller::Color::CornflowerBlue(), impeller::Contents::IsOpaque(), impeller::ConicalGradientContents::SetColors(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [285/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentContextOptionsHasReasonableHashFunctions |
| ) |  |

Definition at line 2613 of file entity_unittests.cc.

2613 {
2614 ContentContextOptions opts;
2615 auto hash_a = ContentContextOptions::Hash{}(opts);
2616
2617 opts.blend_mode = BlendMode::kColorBurn;
2618 auto hash_b = ContentContextOptions::Hash{}(opts);
2619
2620 opts.has_stencil_attachment = false;
2621 auto hash_c = ContentContextOptions::Hash{}(opts);
2622
2623 opts.primitive_type = PrimitiveType::kPoint;
2624 auto hash_d = ContentContextOptions::Hash{}(opts);
2625
2626 EXPECT_NE(hash_a, hash_b);
2627 EXPECT_NE(hash_b, hash_c);
2628 EXPECT_NE(hash_c, hash_d);
2629 }

References impeller::ContentContextOptions::blend_mode, impeller::ContentContextOptions::has_stencil_attachment, impeller::kColorBurn, impeller::kPoint, and impeller::ContentContextOptions::primitive_type.

## ◆ TEST_P() [286/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentsGetBoundsForEmptyPathReturnsNullopt |
| ) |  |

Definition at line 1274 of file entity_unittests.cc.

1274 {
1275 Entity entity;
1276 entity.SetContents(std::make_shared<SolidColorContents>());
1277 ASSERT_FALSE(entity.GetCoverage().has_value());
1278 }

References impeller::Entity::GetCoverage(), and impeller::Entity::SetContents().

## ◆ TEST_P() [287/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CoverageForStrokePathWithNegativeValuesInTransform |
| ) |  |

Definition at line 2328 of file entity_unittests.cc.

2328 {
2329 auto arrow_head = PathBuilder{}
2330 .MoveTo({50, 120})
2331 .LineTo({120, 190})
2332 .LineTo({190, 120})
2333 .TakePath();
2334 auto geometry = Geometry::MakeStrokePath(std::move(arrow_head), 15.0, 4.0,
2335 Cap::kRound, Join::kRound);
2336
2337 auto transform = Matrix::MakeTranslation({300, 300}) *
2338 Matrix::MakeRotationZ(Radians(kPiOver2));
2339 EXPECT_LT(transform.e[0][0], 0.f);
2340 auto coverage = geometry->GetCoverage(transform);
2341 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeXYWH(102.5, 342.5, 85, 155));
2342 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveAndOverlapTest |
| ) |  |

Definition at line 529 of file entity_unittests.cc.

529 {
530 // Compare with https://fiddle.skia.org/c/7a05a3e186c65a8dfb732f68020aae06
531 Path path =
532 PathBuilder{}
533 .MoveTo({359.934, 96.6335})
534 .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
535 {354.673, 96.8895})
536 .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
537 {354.367, 96.9075})
538 .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
539 {349.259, 97.2355})
540 .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
541 {348.625, 97.2834})
542 .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
543 {343.789, 97.6722})
544 .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
545 {342.703, 97.7734})
546 .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
547 {338.246, 98.207})
548 .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
549 {336.612, 98.3894})
550 .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
551 {332.623, 98.8476})
552 .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
553 {332.237, 98.8982})
554 .LineTo({332.237, 102.601})
555 .LineTo({321.778, 102.601})
556 .LineTo({321.778, 100.382})
557 .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
558 {321.161, 100.476})
559 .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
560 {315.332, 101.479})
561 .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
562 {315.301, 101.484})
563 .LineTo({310.017, 105.94})
564 .LineTo({309.779, 105.427})
565 .LineTo({314.403, 101.651})
566 .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
567 {314.368, 101.658})
568 .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
569 {308.846, 102.748})
570 .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
571 .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
572 {303.425, 103.936})
573 .LineTo({299.105, 107.578})
574 .LineTo({298.867, 107.065})
575 .LineTo({302.394, 104.185})
576 .LineTo({302.412, 104.171})
577 .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
578 {299.344, 104.921})
579 .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
580 .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
581 {291.462, 106.979})
582 .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
583 {290.471, 107.257})
584 .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
585 {287.449, 108.139})
586 .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
587 {284.536, 109.035})
588 .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
589 {281.952, 109.859})
590 .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
591 {279.633, 110.638})
592 .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
593 {276.803, 111.607})
594 .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
595 {276.672, 111.653})
596 .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
597 {271.721, 113.463})
598 .LineTo({271.717, 113.449})
599 .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
600 {270.963, 113.628})
601 .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
602 {270.748, 113.682})
603 .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
604 {269.839, 113.926})
605 .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
606 {269.681, 113.972})
607 .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
608 {268.756, 114.239})
609 .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
610 {268.367, 114.354})
611 .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
612 {267.752, 114.54})
613 .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
614 {253.564, 119.252})
615 .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
616 {253.538, 119.261})
617 .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
618 {248.189, 121.131})
619 .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
620 .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
621 {245.975, 121.912})
622 .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
623 {244.698, 122.364})
624 .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
625 {242.794, 123.04})
626 .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
627 {240.961, 123.693})
628 .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
629 {240.052, 124.018})
630 .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
631 .LineTo({237.164, 125.003})
632 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
633 {235.81, 125.538})
634 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
635 {234.592, 125.977})
636 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
637 {234.59, 125.977})
638 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
639 {192.381, 141.429})
640 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
641 .LineTo({360, 160})
642 .LineTo({360, 119.256})
643 .LineTo({360, 106.332})
644 .LineTo({360, 96.6307})
645 .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
646 {359.934, 96.6335})
647 .Close()
648 .MoveTo({337.336, 124.143})
649 .CubicCurveTo({337.274, 122.359}, {338.903, 121.511},
650 {338.903, 121.511})
651 .CubicCurveTo({338.903, 121.511}, {338.96, 123.303},
652 {337.336, 124.143})
653 .Close()
654 .MoveTo({340.082, 121.849})
655 .CubicCurveTo({340.074, 121.917}, {340.062, 121.992},
656 {340.046, 122.075})
657 .CubicCurveTo({340.039, 122.109}, {340.031, 122.142},
658 {340.023, 122.177})
659 .CubicCurveTo({340.005, 122.26}, {339.98, 122.346},
660 {339.952, 122.437})
661 .CubicCurveTo({339.941, 122.473}, {339.931, 122.507},
662 {339.918, 122.544})
663 .CubicCurveTo({339.873, 122.672}, {339.819, 122.804},
664 {339.75, 122.938})
665 .CubicCurveTo({339.747, 122.944}, {339.743, 122.949},
666 {339.74, 122.955})
667 .CubicCurveTo({339.674, 123.08}, {339.593, 123.205},
668 {339.501, 123.328})
669 .CubicCurveTo({339.473, 123.366}, {339.441, 123.401},
670 {339.41, 123.438})
671 .CubicCurveTo({339.332, 123.534}, {339.243, 123.625},
672 {339.145, 123.714})
673 .CubicCurveTo({339.105, 123.75}, {339.068, 123.786},
674 {339.025, 123.821})
675 .CubicCurveTo({338.881, 123.937}, {338.724, 124.048},
676 {338.539, 124.143})
677 .CubicCurveTo({338.532, 123.959}, {338.554, 123.79},
678 {338.58, 123.626})
679 .CubicCurveTo({338.58, 123.625}, {338.58, 123.625}, {338.58, 123.625})
680 .CubicCurveTo({338.607, 123.455}, {338.65, 123.299},
681 {338.704, 123.151})
682 .CubicCurveTo({338.708, 123.14}, {338.71, 123.127},
683 {338.714, 123.117})
684 .CubicCurveTo({338.769, 122.971}, {338.833, 122.838},
685 {338.905, 122.712})
686 .CubicCurveTo({338.911, 122.702}, {338.916, 122.69200000000001},
687 {338.922, 122.682})
688 .CubicCurveTo({338.996, 122.557}, {339.072, 122.444},
689 {339.155, 122.34})
690 .CubicCurveTo({339.161, 122.333}, {339.166, 122.326},
691 {339.172, 122.319})
692 .CubicCurveTo({339.256, 122.215}, {339.339, 122.12},
693 {339.425, 122.037})
694 .CubicCurveTo({339.428, 122.033}, {339.431, 122.03},
695 {339.435, 122.027})
696 .CubicCurveTo({339.785, 121.687}, {340.106, 121.511},
697 {340.106, 121.511})
698 .CubicCurveTo({340.106, 121.511}, {340.107, 121.645},
699 {340.082, 121.849})
700 .Close()
701 .MoveTo({340.678, 113.245})
702 .CubicCurveTo({340.594, 113.488}, {340.356, 113.655},
703 {340.135, 113.775})
704 .CubicCurveTo({339.817, 113.948}, {339.465, 114.059},
705 {339.115, 114.151})
706 .CubicCurveTo({338.251, 114.379}, {337.34, 114.516},
707 {336.448, 114.516})
708 .CubicCurveTo({335.761, 114.516}, {335.072, 114.527},
709 {334.384, 114.513})
710 .CubicCurveTo({334.125, 114.508}, {333.862, 114.462},
711 {333.605, 114.424})
712 .CubicCurveTo({332.865, 114.318}, {332.096, 114.184},
713 {331.41, 113.883})
714 .CubicCurveTo({330.979, 113.695}, {330.442, 113.34},
715 {330.672, 112.813})
716 .CubicCurveTo({331.135, 111.755}, {333.219, 112.946},
717 {334.526, 113.833})
718 .CubicCurveTo({334.54, 113.816}, {334.554, 113.8}, {334.569, 113.784})
719 .CubicCurveTo({333.38, 112.708}, {331.749, 110.985},
720 {332.76, 110.402})
721 .CubicCurveTo({333.769, 109.82}, {334.713, 111.93},
722 {335.228, 113.395})
723 .CubicCurveTo({334.915, 111.889}, {334.59, 109.636},
724 {335.661, 109.592})
725 .CubicCurveTo({336.733, 109.636}, {336.408, 111.889},
726 {336.07, 113.389})
727 .CubicCurveTo({336.609, 111.93}, {337.553, 109.82},
728 {338.563, 110.402})
729 .CubicCurveTo({339.574, 110.984}, {337.942, 112.708},
730 {336.753, 113.784})
731 .CubicCurveTo({336.768, 113.8}, {336.782, 113.816},
732 {336.796, 113.833})
733 .CubicCurveTo({338.104, 112.946}, {340.187, 111.755},
734 {340.65, 112.813})
735 .CubicCurveTo({340.71, 112.95}, {340.728, 113.102},
736 {340.678, 113.245})
737 .Close()
738 .MoveTo({346.357, 106.771})
739 .CubicCurveTo({346.295, 104.987}, {347.924, 104.139},
740 {347.924, 104.139})
741 .CubicCurveTo({347.924, 104.139}, {347.982, 105.931},
742 {346.357, 106.771})
743 .Close()
744 .MoveTo({347.56, 106.771})
745 .CubicCurveTo({347.498, 104.987}, {349.127, 104.139},
746 {349.127, 104.139})
747 .CubicCurveTo({349.127, 104.139}, {349.185, 105.931},
748 {347.56, 106.771})
749 .Close()
750 .TakePath();
751 Entity entity;
752 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
753 entity.SetContents(SolidColorContents::Make(std::move(path), Color::Red()));
754 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
755 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveTest |
| ) |  |

Definition at line 461 of file entity_unittests.cc.

461 {
462 // Compare with https://fiddle.skia.org/c/b3625f26122c9de7afe7794fcf25ead3
463 Path path =
464 PathBuilder{}
465 .MoveTo({237.164, 125.003})
466 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
467 {235.81, 125.538})
468 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
469 {234.592, 125.977})
470 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
471 {234.59, 125.977})
472 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
473 {192.381, 141.429})
474 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
475 .Close()
476 .TakePath();
477 Entity entity;
478 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
479 entity.SetContents(SolidColorContents::Make(std::move(path), Color::Red()));
480 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
481 }

References impeller::Close(), impeller::SolidColorContents::Make(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [290/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DecalSpecializationAppliedToMorphologyFilter |
| ) |  |

Definition at line 2564 of file entity_unittests.cc.

2564 {
2565 auto content_context =
2566 ContentContext(GetContext(), TypographerContextSkia::Make());
2567
2568 auto default_color_burn = content_context.GetMorphologyFilterPipeline({});
2569
2570 auto decal_supported = static_cast<Scalar>(
2571 GetContext()->GetCapabilities()->SupportsDecalSamplerAddressMode());
2572 std::vector<Scalar> expected_constants = {decal_supported};
2573 ASSERT_EQ(default_color_burn->GetDescriptor().GetSpecializationConstants(),
2574 expected_constants);
2575 }

References impeller::TypographerContextSkia::Make().

## ◆ TEST_P() [291/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DoesNotCullEntitiesByDefault |
| ) |  |

Definition at line 1631 of file entity_unittests.cc.

1631 {
1632 auto fill = std::make_shared<SolidColorContents>();
1633 fill->SetColor(Color::CornflowerBlue());
1634 fill->SetGeometry(
1635 Geometry::MakeRect(Rect::MakeLTRB(-1000, -1000, -900, -900)));
1636
1637 Entity entity;
1638 entity.SetContents(fill);
1639
1640 // Even though the entity is offscreen, this should still render because we do
1641 // not compute the coverage intersection by default.
1642 EXPECT_TRUE(entity.ShouldRender(Rect::MakeLTRB(0, 0, 100, 100)));
1643 }

References impeller::Color::CornflowerBlue(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Entity::SetContents(), and impeller::Entity::ShouldRender().

## ◆ TEST_P() [292/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasNoColor |
| ) |  |

Definition at line 1360 of file entity_unittests.cc.

1360 {
1361 // Draws the image as four squares stiched together.
1362 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1363 auto size = atlas->GetSize();
1364 // Divide image into four quadrants.
1365 Scalar half_width = size.width / 2;
1366 Scalar half_height = size.height / 2;
1367 std::vector<Rect> texture_coordinates = {
1368 Rect::MakeLTRB(0, 0, half_width, half_height),
1369 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1370 Rect::MakeLTRB(0, half_height, half_width, size.height),
1371 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1372 // Position quadrants adjacent to eachother.
1373 std::vector<Matrix> transforms = {
1374 Matrix::MakeTranslation({0, 0, 0}),
1375 Matrix::MakeTranslation({half_width, 0, 0}),
1376 Matrix::MakeTranslation({0, half_height, 0}),
1377 Matrix::MakeTranslation({half_width, half_height, 0})};
1378 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1379
1380 contents->SetTransforms(std::move(transforms));
1381 contents->SetTextureCoordinates(std::move(texture_coordinates));
1382 contents->SetTexture(atlas);
1383 contents->SetBlendMode(BlendMode::kSource);
1384
1385 Entity e;
1386 e.SetTransform(Matrix::MakeScale(GetContentScale()));
1387 e.SetContents(contents);
1388
1389 ASSERT_TRUE(OpenPlaygroundHere(std::move(e)));
1390 }

References impeller::kSource, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [293/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasNoColorFullSize |
| ) |  |

Definition at line 1536 of file entity_unittests.cc.

1536 {
1537 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1538 auto size = atlas->GetSize();
1539 std::vector<Rect> texture_coordinates = {
1540 Rect::MakeLTRB(0, 0, size.width, size.height)};
1541 std::vector<Matrix> transforms = {Matrix::MakeTranslation({0, 0, 0})};
1542 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1543
1544 contents->SetTransforms(std::move(transforms));
1545 contents->SetTextureCoordinates(std::move(texture_coordinates));
1546 contents->SetTexture(atlas);
1547 contents->SetBlendMode(BlendMode::kSource);
1548
1549 Entity e;
1550 e.SetTransform(Matrix::MakeScale(GetContentScale()));
1551 e.SetContents(contents);
1552
1553 ASSERT_TRUE(OpenPlaygroundHere(std::move(e)));
1554 }

References impeller::kSource, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [294/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasUsesProvidedCullRectForCoverage |
| ) |  |

Definition at line 1463 of file entity_unittests.cc.

1463 {
1464 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1465 auto size = atlas->GetSize();
1466
1467 Scalar half_width = size.width / 2;
1468 Scalar half_height = size.height / 2;
1469 std::vector<Rect> texture_coordinates = {
1470 Rect::MakeLTRB(0, 0, half_width, half_height),
1471 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1472 Rect::MakeLTRB(0, half_height, half_width, size.height),
1473 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1474 std::vector<Matrix> transforms = {
1475 Matrix::MakeTranslation({0, 0, 0}),
1476 Matrix::MakeTranslation({half_width, 0, 0}),
1477 Matrix::MakeTranslation({0, half_height, 0}),
1478 Matrix::MakeTranslation({half_width, half_height, 0})};
1479
1480 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1481
1482 contents->SetTransforms(std::move(transforms));
1483 contents->SetTextureCoordinates(std::move(texture_coordinates));
1484 contents->SetTexture(atlas);
1485 contents->SetBlendMode(BlendMode::kSource);
1486
1487 auto transform = Matrix::MakeScale(GetContentScale());
1488 Entity e;
1489 e.SetTransform(transform);
1490 e.SetContents(contents);
1491
1492 ASSERT_EQ(contents->GetCoverage(e).value(),
1493 Rect::MakeSize(size).TransformBounds(transform));
1494
1495 contents->SetCullRect(Rect::MakeLTRB(0, 0, 10, 10));
1496
1497 ASSERT_EQ(contents->GetCoverage(e).value(),
1498 Rect::MakeLTRB(0, 0, 10, 10).TransformBounds(transform));
1499 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasWithColorAdvanced |
| ) |  |

Definition at line 1392 of file entity_unittests.cc.

1392 {
1393 // Draws the image as four squares stiched together.
1394 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1395 auto size = atlas->GetSize();
1396 // Divide image into four quadrants.
1397 Scalar half_width = size.width / 2;
1398 Scalar half_height = size.height / 2;
1399 std::vector<Rect> texture_coordinates = {
1400 Rect::MakeLTRB(0, 0, half_width, half_height),
1401 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1402 Rect::MakeLTRB(0, half_height, half_width, size.height),
1403 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1404 // Position quadrants adjacent to eachother.
1405 std::vector<Matrix> transforms = {
1406 Matrix::MakeTranslation({0, 0, 0}),
1407 Matrix::MakeTranslation({half_width, 0, 0}),
1408 Matrix::MakeTranslation({0, half_height, 0}),
1409 Matrix::MakeTranslation({half_width, half_height, 0})};
1410 std::vector<Color> colors = {Color::Red(), Color::Green(), Color::Blue(),
1411 Color::Yellow()};
1412 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1413
1414 contents->SetTransforms(std::move(transforms));
1415 contents->SetTextureCoordinates(std::move(texture_coordinates));
1416 contents->SetTexture(atlas);
1417 contents->SetColors(colors);
1418 contents->SetBlendMode(BlendMode::kModulate);
1419
1420 Entity e;
1421 e.SetTransform(Matrix::MakeScale(GetContentScale()));
1422 e.SetContents(contents);
1423
1424 ASSERT_TRUE(OpenPlaygroundHere(std::move(e)));
1425 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasWithColorSimple |
| ) |  |

Definition at line 1427 of file entity_unittests.cc.

1427 {
1428 // Draws the image as four squares stiched together. Because blend modes
1429 // aren't implented this ends up as four solid color blocks.
1430 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1431 auto size = atlas->GetSize();
1432 // Divide image into four quadrants.
1433 Scalar half_width = size.width / 2;
1434 Scalar half_height = size.height / 2;
1435 std::vector<Rect> texture_coordinates = {
1436 Rect::MakeLTRB(0, 0, half_width, half_height),
1437 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1438 Rect::MakeLTRB(0, half_height, half_width, size.height),
1439 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1440 // Position quadrants adjacent to eachother.
1441 std::vector<Matrix> transforms = {
1442 Matrix::MakeTranslation({0, 0, 0}),
1443 Matrix::MakeTranslation({half_width, 0, 0}),
1444 Matrix::MakeTranslation({0, half_height, 0}),
1445 Matrix::MakeTranslation({half_width, half_height, 0})};
1446 std::vector<Color> colors = {Color::Red(), Color::Green(), Color::Blue(),
1447 Color::Yellow()};
1448 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1449
1450 contents->SetTransforms(std::move(transforms));
1451 contents->SetTextureCoordinates(std::move(texture_coordinates));
1452 contents->SetTexture(atlas);
1453 contents->SetColors(colors);
1454 contents->SetBlendMode(BlendMode::kSourceATop);
1455
1456 Entity e;
1457 e.SetTransform(Matrix::MakeScale(GetContentScale()));
1458 e.SetContents(contents);
1459
1460 ASSERT_TRUE(OpenPlaygroundHere(std::move(e)));
1461 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasWithOpacity |
| ) |  |

Definition at line 1501 of file entity_unittests.cc.

1501 {
1502 // Draws the image as four squares stiched together slightly
1503 // opaque
1504 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1505 auto size = atlas->GetSize();
1506 // Divide image into four quadrants.
1507 Scalar half_width = size.width / 2;
1508 Scalar half_height = size.height / 2;
1509 std::vector<Rect> texture_coordinates = {
1510 Rect::MakeLTRB(0, 0, half_width, half_height),
1511 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1512 Rect::MakeLTRB(0, half_height, half_width, size.height),
1513 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1514 // Position quadrants adjacent to eachother.
1515 std::vector<Matrix> transforms = {
1516 Matrix::MakeTranslation({0, 0, 0}),
1517 Matrix::MakeTranslation({half_width, 0, 0}),
1518 Matrix::MakeTranslation({0, half_height, 0}),
1519 Matrix::MakeTranslation({half_width, half_height, 0})};
1520
1521 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1522
1523 contents->SetTransforms(std::move(transforms));
1524 contents->SetTextureCoordinates(std::move(texture_coordinates));
1525 contents->SetTexture(atlas);
1526 contents->SetBlendMode(BlendMode::kSource);
1527 contents->SetAlpha(0.5);
1528
1529 Entity e;
1530 e.SetTransform(Matrix::MakeScale(GetContentScale()));
1531 e.SetContents(contents);
1532
1533 ASSERT_TRUE(OpenPlaygroundHere(std::move(e)));
1534 }

References impeller::kSource, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [298/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | EntityPassCanMergeSubpassIntoParent |
| ) |  |

Definition at line 145 of file entity_unittests.cc.

145 {
146 // Both a red and a blue box should appear if the pass merging has worked
147 // correctly.
148
149 EntityPass pass;
150 auto subpass = CreatePassWithRectPath(Rect::MakeLTRB(0, 0, 100, 100),
151 Rect::MakeLTRB(50, 50, 150, 150), true);
152 pass.AddSubpass(std::move(subpass));
153
154 Entity entity;
155 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
156 auto contents = std::make_unique<SolidColorContents>();
157 contents->SetGeometry(Geometry::MakeRect(Rect::MakeLTRB(100, 100, 200, 200)));
158 contents->SetColor(Color::Blue());
159 entity.SetContents(std::move(contents));
160
161 pass.AddEntity(std::move(entity));
162
163 ASSERT_TRUE(OpenPlaygroundHere(pass));
164 }

References impeller::EntityPass::AddEntity(), impeller::EntityPass::AddSubpass(), impeller::Color::Blue(), CreatePassWithRectPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [299/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | EntityPassCoverageRespectsCoverageLimit |
| ) |  |

Definition at line 166 of file entity_unittests.cc.

166 {
167 // Rect is drawn entirely in negative area.
168 auto pass = CreatePassWithRectPath(Rect::MakeLTRB(-200, -200, -100, -100),
169 std::nullopt);
170
171 // Without coverage limit.
172 {
173 auto pass_coverage = pass->GetElementsCoverage(std::nullopt);
174 ASSERT_TRUE(pass_coverage.has_value());
175 ASSERT_RECT_NEAR(pass_coverage.value(),
176 Rect::MakeLTRB(-200, -200, -100, -100));
177 }
178
179 // With limit that doesn't overlap.
180 {
181 auto pass_coverage =
182 pass->GetElementsCoverage(Rect::MakeLTRB(0, 0, 100, 100));
183 ASSERT_FALSE(pass_coverage.has_value());
184 }
185
186 // With limit that partially overlaps.
187 {
188 auto pass_coverage =
189 pass->GetElementsCoverage(Rect::MakeLTRB(-150, -150, 0, 0));
190 ASSERT_TRUE(pass_coverage.has_value());
191 ASSERT_RECT_NEAR(pass_coverage.value(),
192 Rect::MakeLTRB(-150, -150, -100, -100));
193 }
194 }

References ASSERT_RECT_NEAR, CreatePassWithRectPath(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [300/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | EntityPassRespectsSubpassBoundsLimit |
| ) |  |

Definition at line 118 of file entity_unittests.cc.

118 {
119 EntityPass pass;
120
121 auto subpass0 = CreatePassWithRectPath(Rect::MakeLTRB(0, 0, 100, 100),
122 Rect::MakeLTRB(50, 50, 150, 150));
123 auto subpass1 = CreatePassWithRectPath(Rect::MakeLTRB(500, 500, 1000, 1000),
124 Rect::MakeLTRB(800, 800, 900, 900));
125
126 auto subpass0_coverage =
127 pass.GetSubpassCoverage(*subpass0.get(), std::nullopt);
128 ASSERT_TRUE(subpass0_coverage.has_value());
129 ASSERT_RECT_NEAR(subpass0_coverage.value(), Rect::MakeLTRB(50, 50, 100, 100));
130
131 auto subpass1_coverage =
132 pass.GetSubpassCoverage(*subpass1.get(), std::nullopt);
133 ASSERT_TRUE(subpass1_coverage.has_value());
134 ASSERT_RECT_NEAR(subpass1_coverage.value(),
135 Rect::MakeLTRB(800, 800, 900, 900));
136
137 pass.AddSubpass(std::move(subpass0));
138 pass.AddSubpass(std::move(subpass1));
139
140 auto coverage = pass.GetElementsCoverage(std::nullopt);
141 ASSERT_TRUE(coverage.has_value());
142 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(50, 50, 900, 900));
143 }

References impeller::EntityPass::AddSubpass(), ASSERT_RECT_NEAR, CreatePassWithRectPath(), impeller::EntityPass::GetElementsCoverage(), impeller::EntityPass::GetSubpassCoverage(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [301/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FilterCoverageRespectsCropRect |
| ) |  |

Definition at line 196 of file entity_unittests.cc.

196 {
197 auto image = CreateTextureForFixture("boston.jpg");
198 auto filter = ColorFilterContents::MakeBlend(BlendMode::kSoftLight,
199 FilterInput::Make({image}));
200
201 // Without the crop rect (default behavior).
202 {
203 auto actual = filter->GetCoverage({});
204 auto expected = Rect::MakeSize(image->GetSize());
205
206 ASSERT_TRUE(actual.has_value());
207 ASSERT_RECT_NEAR(actual.value(), expected);
208 }
209
210 // With the crop rect.
211 {
212 auto expected = Rect::MakeLTRB(50, 50, 100, 100);
213 filter->SetCoverageHint(expected);
214 auto actual = filter->GetCoverage({});
215
216 ASSERT_TRUE(actual.has_value());
217 ASSERT_RECT_NEAR(actual.value(), expected);
218 }
219 }

References ASSERT_RECT_NEAR, impeller::kSoftLight, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST_P() [302/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | Filters |
| ) |  |

Definition at line 960 of file entity_unittests.cc.

960 {
961 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
962 auto boston = CreateTextureForFixture("boston.jpg");
963 auto kalimba = CreateTextureForFixture("kalimba.jpg");
964 ASSERT_TRUE(bridge && boston && kalimba);
965
966 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
967 auto fi_bridge = FilterInput::Make(bridge);
968 auto fi_boston = FilterInput::Make(boston);
969 auto fi_kalimba = FilterInput::Make(kalimba);
970
971 std::shared_ptr<FilterContents> blend0 = ColorFilterContents::MakeBlend(
972 BlendMode::kModulate, {fi_kalimba, fi_boston});
973
974 auto blend1 = ColorFilterContents::MakeBlend(
975 BlendMode::kScreen,
976 {FilterInput::Make(blend0), fi_bridge, fi_bridge, fi_bridge});
977
978 Entity entity;
979 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
980 Matrix::MakeTranslation({500, 300}) *
981 Matrix::MakeScale(Vector2{0.5, 0.5}));
982 entity.SetContents(blend1);
983 return entity.Render(context, pass);
984 };
985 ASSERT_TRUE(OpenPlaygroundHere(callback));
986 }

References impeller::kModulate, impeller::kScreen, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [303/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FramebufferFetchPipelinesDeclareUsage |
| ) |  |

Definition at line 2577 of file entity_unittests.cc.

2577 {
2578 auto content_context =
2579 ContentContext(GetContext(), TypographerContextSkia::Make());
2580 if (!content_context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
2581 GTEST_SKIP() << "Framebuffer fetch not supported.";
2582 }
2583
2584 ContentContextOptions options;
2585 options.color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt;
2586 auto color_burn =
2587 content_context.GetFramebufferBlendColorBurnPipeline(options);
2588
2589 EXPECT_TRUE(color_burn->GetDescriptor().UsesSubpassInput());
2590 }

References impeller::ContentContextOptions::color_attachment_pixel_format, impeller::kR8G8B8A8UNormInt, and impeller::TypographerContextSkia::Make().

## ◆ TEST_P() [304/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GaussianBlurFilter |
| ) |  |

Definition at line 988 of file entity_unittests.cc.

988 {
989 auto boston = CreateTextureForFixture("boston.jpg");
990 ASSERT_TRUE(boston);
991
992 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
993 const char* input_type_names[] = {"Texture", "Solid Color"};
994 const char* blur_type_names[] = {"Image blur", "Mask blur"};
995 const char* pass_variation_names[] = {"New", "2D Directional",
996 "Directional"};
997 const char* blur_style_names[] = {"Normal", "Solid", "Outer", "Inner"};
998 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
999 const FilterContents::BlurStyle blur_styles[] = {
1000 FilterContents::BlurStyle::kNormal, FilterContents::BlurStyle::kSolid,
1001 FilterContents::BlurStyle::kOuter, FilterContents::BlurStyle::kInner};
1002 const Entity::TileMode tile_modes[] = {
1003 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
1004 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
1005
1006 // UI state.
1007 static int selected_input_type = 0;
1008 static Color input_color = Color::Black();
1009 static int selected_blur_type = 0;
1010 static int selected_pass_variation = 0;
1011 static bool combined_sigma = false;
1012 static float blur_amount_coarse[2] = {0, 0};
1013 static float blur_amount_fine[2] = {10, 10};
1014 static int selected_blur_style = 0;
1015 static int selected_tile_mode = 3;
1016 static Color cover_color(1, 0, 0, 0.2);
1017 static Color bounds_color(0, 1, 0, 0.1);
1018 static float offset[2] = {500, 400};
1019 static float rotation = 0;
1020 static float scale[2] = {0.65, 0.65};
1021 static float skew[2] = {0, 0};
1022 static float path_rect[4] = {0, 0,
1023 static_cast<float>(boston->GetSize().width),
1024 static_cast<float>(boston->GetSize().height)};
1025
1026 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1027 {
1028 ImGui::Combo("Input type", &selected_input_type, input_type_names,
1029 sizeof(input_type_names) / sizeof(char*));
1030 if (selected_input_type == 0) {
1031 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1032 } else {
1033 ImGui::ColorEdit4("Input color",
1034 reinterpret_cast<float*>(&input_color));
1035 }
1036 ImGui::Combo("Blur type", &selected_blur_type, blur_type_names,
1037 sizeof(blur_type_names) / sizeof(char*));
1038 if (selected_blur_type == 0) {
1039 ImGui::Combo("Pass variation", &selected_pass_variation,
1040 pass_variation_names,
1041 sizeof(pass_variation_names) / sizeof(char*));
1042 }
1043 ImGui::Checkbox("Combined sigma", &combined_sigma);
1044 if (combined_sigma) {
1045 ImGui::SliderFloat("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1046 ImGui::SliderFloat("Sigma (fine)", blur_amount_fine, 0, 10);
1047 blur_amount_coarse[1] = blur_amount_coarse[0];
1048 blur_amount_fine[1] = blur_amount_fine[0];
1049 } else {
1050 ImGui::SliderFloat2("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1051 ImGui::SliderFloat2("Sigma (fine)", blur_amount_fine, 0, 10);
1052 }
1053 ImGui::Combo("Blur style", &selected_blur_style, blur_style_names,
1054 sizeof(blur_style_names) / sizeof(char*));
1055 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1056 sizeof(tile_mode_names) / sizeof(char*));
1057 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1058 ImGui::ColorEdit4("Bounds color",
1059 reinterpret_cast<float*>(&bounds_color));
1060 ImGui::SliderFloat2("Translation", offset, 0,
1061 pass.GetRenderTargetSize().width);
1062 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1063 ImGui::SliderFloat2("Scale", scale, 0, 3);
1064 ImGui::SliderFloat2("Skew", skew, -3, 3);
1065 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1066 }
1067 ImGui::End();
1068
1069 auto blur_sigma_x = Sigma{blur_amount_coarse[0] + blur_amount_fine[0]};
1070 auto blur_sigma_y = Sigma{blur_amount_coarse[1] + blur_amount_fine[1]};
1071
1072 std::shared_ptr<Contents> input;
1073 Size input_size;
1074
1075 auto input_rect =
1076 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1077 if (selected_input_type == 0) {
1078 auto texture = std::make_shared<TextureContents>();
1079 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1080 texture->SetDestinationRect(input_rect);
1081 texture->SetTexture(boston);
1082 texture->SetOpacity(input_color.alpha);
1083
1084 input = texture;
1085 input_size = input_rect.GetSize();
1086 } else {
1087 auto fill = std::make_shared<SolidColorContents>();
1088 fill->SetColor(input_color);
1089 fill->SetGeometry(
1090 Geometry::MakeFillPath(PathBuilder{}.AddRect(input_rect).TakePath()));
1091
1092 input = fill;
1093 input_size = input_rect.GetSize();
1094 }
1095
1096 std::shared_ptr<FilterContents> blur;
1097 switch (selected_pass_variation) {
1098 case 0:
1099 blur = std::make_shared<GaussianBlurFilterContents>(
1100 blur_sigma_x.sigma, blur_sigma_y.sigma,
1101 tile_modes[selected_tile_mode]);
1102 blur->SetInputs({FilterInput::Make(input)});
1103 break;
1104 case 1:
1105 blur = FilterContents::MakeGaussianBlur(
1106 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1107 blur_styles[selected_blur_style], tile_modes[selected_tile_mode]);
1108 break;
1109 case 2: {
1110 Vector2 blur_vector(blur_sigma_x.sigma, blur_sigma_y.sigma);
1111 blur = FilterContents::MakeDirectionalGaussianBlur(
1112 FilterInput::Make(input), Sigma{blur_vector.GetLength()},
1113 blur_vector.Normalize());
1114 break;
1115 }
1116 };
1117 FML_CHECK(blur);
1118
1119 auto mask_blur = FilterContents::MakeBorderMaskBlur(
1120 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1121 blur_styles[selected_blur_style]);
1122
1123 auto ctm = Matrix::MakeScale(GetContentScale()) *
1124 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1125 Matrix::MakeRotationZ(Radians(rotation)) *
1126 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1127 Matrix::MakeSkew(skew[0], skew[1]) *
1128 Matrix::MakeTranslation(-Point(input_size) / 2);
1129
1130 auto target_contents = selected_blur_type == 0 ? blur : mask_blur;
1131
1132 Entity entity;
1133 entity.SetContents(target_contents);
1134 entity.SetTransform(ctm);
1135
1136 entity.Render(context, pass);
1137
1138 // Renders a red "cover" rectangle that shows the original position of the
1139 // unfiltered input.
1140 Entity cover_entity;
1141 cover_entity.SetContents(SolidColorContents::Make(
1142 PathBuilder{}.AddRect(input_rect).TakePath(), cover_color));
1143 cover_entity.SetTransform(ctm);
1144
1145 cover_entity.Render(context, pass);
1146
1147 // Renders a green bounding rect of the target filter.
1148 Entity bounds_entity;
1149 std::optional<Rect> target_contents_coverage =
1150 target_contents->GetCoverage(entity);
1151 if (target_contents_coverage.has_value()) {
1152 bounds_entity.SetContents(SolidColorContents::Make(
1153 PathBuilder{}
1154 .AddRect(target_contents->GetCoverage(entity).value())
1155 .TakePath(),
1156 bounds_color));
1157 bounds_entity.SetTransform(Matrix());
1158
1159 bounds_entity.Render(context, pass);
1160 }
1161
1162 return true;
1163 };
1164 ASSERT_TRUE(OpenPlaygroundHere(callback));
1165 }

References impeller::PathBuilder::AddRect(), impeller::Color::alpha, impeller::Color::Black(), impeller::Entity::GetCoverage(), impeller::TPoint< T >::GetLength(), 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::FilterContents::MakeDirectionalGaussianBlur(), impeller::Geometry::MakeFillPath(), impeller::FilterContents::MakeGaussianBlur(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeSize(), impeller::Matrix::MakeSkew(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::TPoint< T >::Normalize(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [305/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GeometryBoundsAreTransformed |
| ) |  |

Definition at line 249 of file entity_unittests.cc.

249 {
250 auto geometry = Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100));
251 auto transform = Matrix::MakeScale({2.0, 2.0, 2.0});
252
253 ASSERT_RECT_NEAR(geometry->GetCoverage(transform).value(),
254 Rect::MakeXYWH(200, 200, 200, 200));
255 }

References ASSERT_RECT_NEAR, impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [306/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | InheritOpacityTest |
| ) |  |

Definition at line 2178 of file entity_unittests.cc.

2178 {
2179 Entity entity;
2180
2181 // Texture contents can always accept opacity.
2182 auto texture_contents = std::make_shared<TextureContents>();
2183 texture_contents->SetOpacity(0.5);
2184 ASSERT_TRUE(texture_contents->CanInheritOpacity(entity));
2185
2186 texture_contents->SetInheritedOpacity(0.5);
2187 ASSERT_EQ(texture_contents->GetOpacity(), 0.25);
2188 texture_contents->SetInheritedOpacity(0.5);
2189 ASSERT_EQ(texture_contents->GetOpacity(), 0.25);
2190
2191 // Solid color contents can accept opacity if their geometry
2192 // doesn't overlap.
2193 auto solid_color = std::make_shared<SolidColorContents>();
2194 solid_color->SetGeometry(
2195 Geometry::MakeRect(Rect::MakeLTRB(100, 100, 200, 200)));
2196 solid_color->SetColor(Color::Blue().WithAlpha(0.5));
2197
2198 ASSERT_TRUE(solid_color->CanInheritOpacity(entity));
2199
2200 solid_color->SetInheritedOpacity(0.5);
2201 ASSERT_EQ(solid_color->GetColor().alpha, 0.25);
2202 solid_color->SetInheritedOpacity(0.5);
2203 ASSERT_EQ(solid_color->GetColor().alpha, 0.25);
2204
2205 // Color source contents can accept opacity if their geometry
2206 // doesn't overlap.
2207 auto tiled_texture = std::make_shared<TiledTextureContents>();
2208 tiled_texture->SetGeometry(
2209 Geometry::MakeRect(Rect::MakeLTRB(100, 100, 200, 200)));
2210 tiled_texture->SetOpacityFactor(0.5);
2211
2212 ASSERT_TRUE(tiled_texture->CanInheritOpacity(entity));
2213
2214 tiled_texture->SetInheritedOpacity(0.5);
2215 ASSERT_EQ(tiled_texture->GetOpacityFactor(), 0.25);
2216 tiled_texture->SetInheritedOpacity(0.5);
2217 ASSERT_EQ(tiled_texture->GetOpacityFactor(), 0.25);
2218
2219 // Text contents can accept opacity if the text frames do not
2220 // overlap
2221 SkFont font = flutter::testing::CreateTestFontOfSize(30);
2222 auto blob = SkTextBlob::MakeFromString("A", font);
2223 auto frame = MakeTextFrameFromTextBlobSkia(blob);
2224 auto lazy_glyph_atlas =
2225 std::make_shared<LazyGlyphAtlas>(TypographerContextSkia::Make());
2226 lazy_glyph_atlas->AddTextFrame(*frame, 1.0f);
2227
2228 auto text_contents = std::make_shared<TextContents>();
2229 text_contents->SetTextFrame(frame);
2230 text_contents->SetColor(Color::Blue().WithAlpha(0.5));
2231
2232 ASSERT_TRUE(text_contents->CanInheritOpacity(entity));
2233
2234 text_contents->SetInheritedOpacity(0.5);
2235 ASSERT_EQ(text_contents->GetColor().alpha, 0.25);
2236 text_contents->SetInheritedOpacity(0.5);
2237 ASSERT_EQ(text_contents->GetColor().alpha, 0.25);
2238
2239 // Clips and restores trivially accept opacity.
2240 ASSERT_TRUE(ClipContents().CanInheritOpacity(entity));
2241 ASSERT_TRUE(ClipRestoreContents().CanInheritOpacity(entity));
2242
2243 // Runtime effect contents can't accept opacity.
2244 auto runtime_effect = std::make_shared<RuntimeEffectContents>();
2245 ASSERT_FALSE(runtime_effect->CanInheritOpacity(entity));
2246 }

References impeller::Color::Blue(), impeller::TypographerContextSkia::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [307/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearGradientContentsIsOpaque |
| ) |  |

Definition at line 2360 of file entity_unittests.cc.

2360 {
2361 LinearGradientContents contents;
2362 contents.SetColors({Color::CornflowerBlue()});
2363 ASSERT_TRUE(contents.IsOpaque());
2364 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2365 ASSERT_FALSE(contents.IsOpaque());
2366 contents.SetColors({Color::CornflowerBlue()});
2367 contents.SetTileMode(Entity::TileMode::kDecal);
2368 ASSERT_FALSE(contents.IsOpaque());
2369 }

References impeller::Color::CornflowerBlue(), impeller::LinearGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::LinearGradientContents::SetColors(), impeller::LinearGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [308/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilter |
| ) |  |

Definition at line 1887 of file entity_unittests.cc.

1887 {
1888 auto image = CreateTextureForFixture("kalimba.jpg");
1889 ASSERT_TRUE(image);
1890
1891 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1892 auto filtered =
1893 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(image));
1894
1895 // Define the entity that will serve as the control image as a Gaussian blur
1896 // filter with no filter at all.
1897 Entity entity_left;
1898 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1899 Matrix::MakeTranslation({100, 300}) *
1900 Matrix::MakeScale(Vector2{0.5, 0.5}));
1901 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1902 Sigma{0}, Sigma{0});
1903 entity_left.SetContents(unfiltered);
1904
1905 // Define the entity that will be filtered from linear to sRGB.
1906 Entity entity_right;
1907 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1908 Matrix::MakeTranslation({500, 300}) *
1909 Matrix::MakeScale(Vector2{0.5, 0.5}));
1910 entity_right.SetContents(filtered);
1911 return entity_left.Render(context, pass) &&
1912 entity_right.Render(context, pass);
1913 };
1914
1915 ASSERT_TRUE(OpenPlaygroundHere(callback));
1916 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilterCoverageIsCorrect |
| ) |  |

Definition at line 1866 of file entity_unittests.cc.

1866 {
1867 // Set up a simple color background.
1868 auto fill = std::make_shared<SolidColorContents>();
1869 fill->SetGeometry(Geometry::MakeFillPath(
1870 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1871 fill->SetColor(Color::MintCream());
1872
1873 auto filter =
1874 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(fill));
1875
1876 Entity e;
1877 e.SetTransform(Matrix());
1878
1879 // Confirm that the actual filter coverage matches the expected coverage.
1880 auto actual = filter->GetCoverage(e);
1881 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1882
1883 ASSERT_TRUE(actual.has_value());
1884 ASSERT_RECT_NEAR(actual.value(), expected);
1885 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | MorphologyFilter |
| ) |  |

Definition at line 1167 of file entity_unittests.cc.

1167 {
1168 auto boston = CreateTextureForFixture("boston.jpg");
1169 ASSERT_TRUE(boston);
1170
1171 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1172 const char* morphology_type_names[] = {"Dilate", "Erode"};
1173 const FilterContents::MorphType morphology_types[] = {
1174 FilterContents::MorphType::kDilate, FilterContents::MorphType::kErode};
1175 static Color input_color = Color::Black();
1176 // UI state.
1177 static int selected_morphology_type = 0;
1178 static float radius[2] = {20, 20};
1179 static Color cover_color(1, 0, 0, 0.2);
1180 static Color bounds_color(0, 1, 0, 0.1);
1181 static float offset[2] = {500, 400};
1182 static float rotation = 0;
1183 static float scale[2] = {0.65, 0.65};
1184 static float skew[2] = {0, 0};
1185 static float path_rect[4] = {0, 0,
1186 static_cast<float>(boston->GetSize().width),
1187 static_cast<float>(boston->GetSize().height)};
1188 static float effect_transform_scale = 1;
1189
1190 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1191 {
1192 ImGui::Combo("Morphology type", &selected_morphology_type,
1193 morphology_type_names,
1194 sizeof(morphology_type_names) / sizeof(char*));
1195 ImGui::SliderFloat2("Radius", radius, 0, 200);
1196 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1197 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1198 ImGui::ColorEdit4("Bounds color",
1199 reinterpret_cast<float*>(&bounds_color));
1200 ImGui::SliderFloat2("Translation", offset, 0,
1201 pass.GetRenderTargetSize().width);
1202 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1203 ImGui::SliderFloat2("Scale", scale, 0, 3);
1204 ImGui::SliderFloat2("Skew", skew, -3, 3);
1205 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1206 ImGui::SliderFloat("Effect transform scale", &effect_transform_scale, 0,
1207 3);
1208 }
1209 ImGui::End();
1210
1211 std::shared_ptr<Contents> input;
1212 Size input_size;
1213
1214 auto input_rect =
1215 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1216 auto texture = std::make_shared<TextureContents>();
1217 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1218 texture->SetDestinationRect(input_rect);
1219 texture->SetTexture(boston);
1220 texture->SetOpacity(input_color.alpha);
1221
1222 input = texture;
1223 input_size = input_rect.GetSize();
1224
1225 auto contents = FilterContents::MakeMorphology(
1226 FilterInput::Make(input), Radius{radius[0]}, Radius{radius[1]},
1227 morphology_types[selected_morphology_type]);
1228 contents->SetEffectTransform(Matrix::MakeScale(
1229 Vector2{effect_transform_scale, effect_transform_scale}));
1230
1231 auto ctm = Matrix::MakeScale(GetContentScale()) *
1232 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1233 Matrix::MakeRotationZ(Radians(rotation)) *
1234 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1235 Matrix::MakeSkew(skew[0], skew[1]) *
1236 Matrix::MakeTranslation(-Point(input_size) / 2);
1237
1238 Entity entity;
1239 entity.SetContents(contents);
1240 entity.SetTransform(ctm);
1241
1242 entity.Render(context, pass);
1243
1244 // Renders a red "cover" rectangle that shows the original position of the
1245 // unfiltered input.
1246 Entity cover_entity;
1247 cover_entity.SetContents(SolidColorContents::Make(
1248 PathBuilder{}.AddRect(input_rect).TakePath(), cover_color));
1249 cover_entity.SetTransform(ctm);
1250
1251 cover_entity.Render(context, pass);
1252
1253 // Renders a green bounding rect of the target filter.
1254 Entity bounds_entity;
1255 bounds_entity.SetContents(SolidColorContents::Make(
1256 PathBuilder{}.AddRect(contents->GetCoverage(entity).value()).TakePath(),
1257 bounds_color));
1258 bounds_entity.SetTransform(Matrix());
1259
1260 bounds_entity.Render(context, pass);
1261
1262 return true;
1263 };
1264 ASSERT_TRUE(OpenPlaygroundHere(callback));
1265 }

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(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [311/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | PipelineDescriptorEqAndHash |
| ) |  |

Definition at line 2592 of file entity_unittests.cc.

2592 {
2593 auto desc_1 = std::make_shared<PipelineDescriptor>();
2594 auto desc_2 = std::make_shared<PipelineDescriptor>();
2595
2596 EXPECT_TRUE(desc_1->IsEqual(*desc_2));
2597 EXPECT_EQ(desc_1->GetHash(), desc_2->GetHash());
2598
2599 desc_1->SetUseSubpassInput(UseSubpassInput::kYes);
2600
2601 EXPECT_FALSE(desc_1->IsEqual(*desc_2));
2602 EXPECT_NE(desc_1->GetHash(), desc_2->GetHash());
2603
2604 desc_2->SetUseSubpassInput(UseSubpassInput::kYes);
2605
2606 EXPECT_TRUE(desc_1->IsEqual(*desc_2));
2607 EXPECT_EQ(desc_1->GetHash(), desc_2->GetHash());
2608 }

References impeller::kYes.

## ◆ TEST_P() [312/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | PointFieldCanUseCompute |
| ) |  |

Definition at line 2429 of file entity_unittests.cc.

2429 {
2430 EXPECT_EQ(PointFieldGeometry::CanUseCompute(*GetContentContext()),
2431 GetContext()->GetBackendType() == Context::BackendType::kMetal);
2432 }

References impeller::PointFieldGeometry::CanUseCompute(), and impeller::Context::kMetal.

## ◆ TEST_P() [313/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | PointFieldGeometryCoverage |
| ) |  |

Definition at line 2421 of file entity_unittests.cc.

2421 {
2422 std::vector<Point> points = {{10, 20}, {100, 200}};
2423 auto geometry = Geometry::MakePointField(points, 5.0, false);
2424 ASSERT_EQ(*geometry->GetCoverage(Matrix()), Rect::MakeLTRB(5, 15, 105, 205));
2425 ASSERT_EQ(*geometry->GetCoverage(Matrix::MakeTranslation({30, 0, 0})),
2426 Rect::MakeLTRB(35, 15, 135, 205));
2427 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakePointField(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [314/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | PointFieldGeometryDivisions |
| ) |  |

Definition at line 2403 of file entity_unittests.cc.

2403 {
2404 // Square always gives 4 divisions.
2405 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(24.0, false), 4u);
2406 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(2.0, false), 4u);
2407 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(200.0, false), 4u);
2408
2409 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(0.5, true), 4u);
2410 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(1.5, true), 8u);
2411 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(5.5, true), 24u);
2412 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(12.5, true), 34u);
2413 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(22.3, true), 22u);
2414 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(40.5, true), 40u);
2415 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(100.0, true), 100u);
2416 // Caps at 140.
2417 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(1000.0, true), 140u);
2418 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(20000.0, true), 140u);
2419 }

References impeller::PointFieldGeometry::ComputeCircleDivisions().

## ◆ TEST_P() [315/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RadialGradientContentsIsOpaque |
| ) |  |

Definition at line 2371 of file entity_unittests.cc.

2371 {
2372 RadialGradientContents contents;
2373 contents.SetColors({Color::CornflowerBlue()});
2374 ASSERT_TRUE(contents.IsOpaque());
2375 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2376 ASSERT_FALSE(contents.IsOpaque());
2377 contents.SetColors({Color::CornflowerBlue()});
2378 contents.SetTileMode(Entity::TileMode::kDecal);
2379 ASSERT_FALSE(contents.IsOpaque());
2380 }

References impeller::Color::CornflowerBlue(), impeller::RadialGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::RadialGradientContents::SetColors(), impeller::RadialGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [316/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RendersDstPerColorWithAlpha |
| ) |  |

Definition at line 43 of file vertices_contents_unittests.cc.

43 {
44 using FS = GeometryColorPipeline::FragmentShader;
45
46 auto contents = std::make_shared<VerticesContents>();
47 auto vertices = CreateColorVertices(
48 {{0, 0}, {100, 0}, {0, 100}, {100, 0}, {0, 100}, {100, 100}},
49 {Color::Red(), Color::Red(), Color::Red(), Color::Red(), Color::Red(),
50 Color::Red()});
51 auto src_contents = SolidColorContents::Make(
52 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath(),
53 Color::Red());
54
55 contents->SetGeometry(vertices);
56 contents->SetAlpha(0.5);
57 contents->SetBlendMode(BlendMode::kDestination);
58 contents->SetSourceContents(std::move(src_contents));
59
60 auto content_context = GetContentContext();
61 auto buffer = content_context->GetContext()->CreateCommandBuffer();
62 auto render_target = RenderTarget::CreateOffscreenMSAA(
63 *content_context->GetContext(),
64 *GetContentContext()->GetRenderTargetCache(), {100, 100});
65 auto render_pass = buffer->CreateRenderPass(render_target);
66 Entity entity;
67
68 ASSERT_TRUE(render_pass->GetCommands().empty());
69 ASSERT_TRUE(contents->Render(*content_context, entity, *render_pass));
70
71 const auto& cmd = render_pass->GetCommands()[0];
72 auto* frag_uniforms = GetFragInfo<FS>(cmd);
73
74 ASSERT_EQ(frag_uniforms->alpha, 0.5);
75 }

References impeller::PathBuilder::AddRect(), CreateColorVertices(), impeller::RenderTarget::CreateOffscreenMSAA(), impeller::kDestination, impeller::SolidColorContents::Make(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::Color::Red().

## ◆ TEST_P() [317/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RRectShadowTest |
| ) |  |

Definition at line 1729 of file entity_unittests.cc.

1729 {
1730 auto callback = [&](ContentContext& context, RenderPass& pass) {
1731 static Color color = Color::Red();
1732 static float corner_radius = 100;
1733 static float blur_radius = 100;
1734 static bool show_coverage = false;
1735 static Color coverage_color = Color::Green().WithAlpha(0.2);
1736
1737 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1738 ImGui::SliderFloat("Corner radius", &corner_radius, 0, 300);
1739 ImGui::SliderFloat("Blur radius", &blur_radius, 0, 300);
1740 ImGui::ColorEdit4("Color", reinterpret_cast<Scalar*>(&color));
1741 ImGui::Checkbox("Show coverage", &show_coverage);
1742 if (show_coverage) {
1743 ImGui::ColorEdit4("Coverage color",
1744 reinterpret_cast<Scalar*>(&coverage_color));
1745 }
1746 ImGui::End();
1747
1748 auto [top_left, bottom_right] = IMPELLER_PLAYGROUND_LINE(
1749 Point(200, 200), Point(600, 400), 30, Color::White(), Color::White());
1750 auto rect =
1751 Rect::MakeLTRB(top_left.x, top_left.y, bottom_right.x, bottom_right.y);
1752
1753 auto contents = std::make_unique<SolidRRectBlurContents>();
1754 contents->SetRRect(rect, {corner_radius, corner_radius});
1755 contents->SetColor(color);
1756 contents->SetSigma(Radius(blur_radius));
1757
1758 Entity entity;
1759 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
1760 entity.SetContents(std::move(contents));
1761 entity.Render(context, pass);
1762
1763 auto coverage = entity.GetCoverage();
1764 if (show_coverage && coverage.has_value()) {
1765 auto bounds_contents = std::make_unique<SolidColorContents>();
1766 bounds_contents->SetGeometry(Geometry::MakeFillPath(
1767 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath()));
1768 bounds_contents->SetColor(coverage_color.Premultiply());
1769 Entity bounds_entity;
1770 bounds_entity.SetContents(std::move(bounds_contents));
1771 bounds_entity.Render(context, pass);
1772 }
1773
1774 return true;
1775 };
1776 ASSERT_TRUE(OpenPlaygroundHere(callback));
1777 }

References impeller::PathBuilder::AddRect(), impeller::Entity::GetCoverage(), impeller::Color::Green(), IMPELLER_PLAYGROUND_LINE, 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() [318/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffect |
| ) |  |

Definition at line 2134 of file entity_unittests.cc.

2134 {
2135 if (!BackendSupportsFragmentProgram()) {
2136 GTEST_SKIP_("This backend doesn't support runtime effects.");
2137 }
2138
2139 auto runtime_stages =
2140 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2141 auto runtime_stage =
2142 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2143 ASSERT_TRUE(runtime_stage);
2144 ASSERT_TRUE(runtime_stage->IsDirty());
2145
2146 bool first_frame = true;
2147 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2148 if (first_frame) {
2149 first_frame = false;
2150 } else {
2151 assert(runtime_stage->IsDirty() == false);
2152 }
2153
2154 auto contents = std::make_shared<RuntimeEffectContents>();
2155 contents->SetGeometry(Geometry::MakeCover());
2156
2157 contents->SetRuntimeStage(runtime_stage);
2158
2159 struct FragUniforms {
2160 Vector2 iResolution;
2161 Scalar iTime;
2162 } frag_uniforms = {
2163 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
2164 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
2165 };
2166 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2167 uniform_data->resize(sizeof(FragUniforms));
2168 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2169 contents->SetUniformData(uniform_data);
2170
2171 Entity entity;
2172 entity.SetContents(contents);
2173 return contents->Render(context, entity, pass);
2174 };
2175 ASSERT_TRUE(OpenPlaygroundHere(callback));
2176 }

References impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [319/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SetBlendMode |
| ) |  |

Definition at line 1267 of file entity_unittests.cc.

1267 {
1268 Entity entity;
1269 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kSourceOver);
1270 entity.SetBlendMode(BlendMode::kClear);
1271 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kClear);
1272 }

References impeller::Entity::GetBlendMode(), impeller::kClear, impeller::kSourceOver, and impeller::Entity::SetBlendMode().

## ◆ TEST_P() [320/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsIsOpaque |
| ) |  |

Definition at line 2344 of file entity_unittests.cc.

2344 {
2345 SolidColorContents contents;
2346 contents.SetColor(Color::CornflowerBlue());
2347 ASSERT_TRUE(contents.IsOpaque());
2348 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.5));
2349 ASSERT_FALSE(contents.IsOpaque());
2350 }

References impeller::Color::CornflowerBlue(), impeller::SolidColorContents::IsOpaque(), and impeller::SolidColorContents::SetColor().

## ◆ TEST_P() [321/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetMiterLimit |
| ) |  |

Definition at line 779 of file entity_unittests.cc.

779 {
780 {
781 auto geometry = Geometry::MakeStrokePath(Path{});
782 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
783 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
784 }
785
786 {
787 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, /*miter_limit=*/8.0);
788 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
789 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 8);
790 }
791
792 {
793 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, /*miter_limit=*/-1.0);
794 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
795 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
796 }
797 }

References impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [322/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetStrokeCapsAndJoins |
| ) |  |

Definition at line 757 of file entity_unittests.cc.

757 {
758 {
759 auto geometry = Geometry::MakeStrokePath(Path{});
760 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
761 // Defaults.
762 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kButt);
763 ASSERT_EQ(path_geometry->GetStrokeJoin(), Join::kMiter);
764 }
765
766 {
767 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kSquare);
768 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
769 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kSquare);
770 }
771
772 {
773 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kRound);
774 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
775 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kRound);
776 }
777 }

References impeller::kButt, impeller::kMiter, impeller::kRound, impeller::kSquare, and impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [323/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidFillCoverageIsCorrect |
| ) |  |

Definition at line 1556 of file entity_unittests.cc.

1556 {
1557 // No transform
1558 {
1559 auto fill = std::make_shared<SolidColorContents>();
1560 fill->SetColor(Color::CornflowerBlue());
1561 auto expected = Rect::MakeLTRB(100, 110, 200, 220);
1562 fill->SetGeometry(
1563 Geometry::MakeFillPath(PathBuilder{}.AddRect(expected).TakePath()));
1564
1565 auto coverage = fill->GetCoverage({});
1566 ASSERT_TRUE(coverage.has_value());
1567 ASSERT_RECT_NEAR(coverage.value(), expected);
1568 }
1569
1570 // Entity transform
1571 {
1572 auto fill = std::make_shared<SolidColorContents>();
1573 fill->SetColor(Color::CornflowerBlue());
1574 fill->SetGeometry(Geometry::MakeFillPath(
1575 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath()));
1576
1577 Entity entity;
1578 entity.SetTransform(Matrix::MakeTranslation(Vector2(4, 5)));
1579 entity.SetContents(std::move(fill));
1580
1581 auto coverage = entity.GetCoverage();
1582 auto expected = Rect::MakeLTRB(104, 115, 204, 225);
1583 ASSERT_TRUE(coverage.has_value());
1584 ASSERT_RECT_NEAR(coverage.value(), expected);
1585 }
1586
1587 // No coverage for fully transparent colors
1588 {
1589 auto fill = std::make_shared<SolidColorContents>();
1590 fill->SetColor(Color::WhiteTransparent());
1591 fill->SetGeometry(Geometry::MakeFillPath(
1592 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath()));
1593
1594 auto coverage = fill->GetCoverage({});
1595 ASSERT_FALSE(coverage.has_value());
1596 }
1597 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidFillShouldRenderIsCorrect |
| ) |  |

Definition at line 1599 of file entity_unittests.cc.

1599 {
1600 // No path.
1601 {
1602 auto fill = std::make_shared<SolidColorContents>();
1603 fill->SetColor(Color::CornflowerBlue());
1604 ASSERT_FALSE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1605 ASSERT_FALSE(
1606 fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1607 }
1608
1609 // With path.
1610 {
1611 auto fill = std::make_shared<SolidColorContents>();
1612 fill->SetColor(Color::CornflowerBlue());
1613 fill->SetGeometry(Geometry::MakeFillPath(
1614 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1615 ASSERT_TRUE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1616 ASSERT_FALSE(
1617 fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1618 }
1619
1620 // With paint cover.
1621 {
1622 auto fill = std::make_shared<SolidColorContents>();
1623 fill->SetColor(Color::CornflowerBlue());
1624 fill->SetGeometry(Geometry::MakeCover());
1625 ASSERT_TRUE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1626 ASSERT_TRUE(
1627 fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1628 }
1629 }

References impeller::PathBuilder::AddRect(), impeller::Color::CornflowerBlue(), impeller::Geometry::MakeCover(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST_P() [325/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidStrokeCoverageIsCorrect |
| ) |  |

Definition at line 1280 of file entity_unittests.cc.

1280 {
1281 {
1282 auto geometry = Geometry::MakeStrokePath(
1283 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1284 Cap::kButt, Join::kBevel);
1285
1286 Entity entity;
1287 auto contents = std::make_unique<SolidColorContents>();
1288 contents->SetGeometry(std::move(geometry));
1289 contents->SetColor(Color::Black());
1290 entity.SetContents(std::move(contents));
1291 auto actual = entity.GetCoverage();
1292 auto expected = Rect::MakeLTRB(-2, -2, 12, 12);
1293 ASSERT_TRUE(actual.has_value());
1294 ASSERT_RECT_NEAR(actual.value(), expected);
1295 }
1296
1297 // Cover the Cap::kSquare case.
1298 {
1299 auto geometry = Geometry::MakeStrokePath(
1300 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1301 Cap::kSquare, Join::kBevel);
1302
1303 Entity entity;
1304 auto contents = std::make_unique<SolidColorContents>();
1305 contents->SetGeometry(std::move(geometry));
1306 contents->SetColor(Color::Black());
1307 entity.SetContents(std::move(contents));
1308 auto actual = entity.GetCoverage();
1309 auto expected =
1310 Rect::MakeLTRB(-sqrt(8), -sqrt(8), 10 + sqrt(8), 10 + sqrt(8));
1311 ASSERT_TRUE(actual.has_value());
1312 ASSERT_RECT_NEAR(actual.value(), expected);
1313 }
1314
1315 // Cover the Join::kMiter case.
1316 {
1317 auto geometry = Geometry::MakeStrokePath(
1318 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 2.0,
1319 Cap::kSquare, Join::kMiter);
1320
1321 Entity entity;
1322 auto contents = std::make_unique<SolidColorContents>();
1323 contents->SetGeometry(std::move(geometry));
1324 contents->SetColor(Color::Black());
1325 entity.SetContents(std::move(contents));
1326 auto actual = entity.GetCoverage();
1327 auto expected = Rect::MakeLTRB(-4, -4, 14, 14);
1328 ASSERT_TRUE(actual.has_value());
1329 ASSERT_RECT_NEAR(actual.value(), expected);
1330 }
1331 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SpecializationConstantsAreAppliedToVariants |
| ) |  |

Definition at line 2544 of file entity_unittests.cc.

2544 {
2545 auto content_context =
2546 ContentContext(GetContext(), TypographerContextSkia::Make());
2547
2548 auto default_color_burn = content_context.GetBlendColorBurnPipeline(
2549 {.has_stencil_attachment = false});
2550 auto alt_color_burn = content_context.GetBlendColorBurnPipeline(
2551 {.has_stencil_attachment = true});
2552
2553 ASSERT_NE(default_color_burn, alt_color_burn);
2554 ASSERT_EQ(default_color_burn->GetDescriptor().GetSpecializationConstants(),
2555 alt_color_burn->GetDescriptor().GetSpecializationConstants());
2556
2557 auto decal_supported = static_cast<Scalar>(
2558 GetContext()->GetCapabilities()->SupportsDecalSamplerAddressMode());
2559 std::vector<Scalar> expected_constants = {5, decal_supported};
2560 ASSERT_EQ(default_color_burn->GetDescriptor().GetSpecializationConstants(),
2561 expected_constants);
2562 }

References impeller::TypographerContextSkia::Make().

## ◆ TEST_P() [327/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilter |
| ) |  |

Definition at line 1939 of file entity_unittests.cc.

1939 {
1940 auto image = CreateTextureForFixture("embarcadero.jpg");
1941 ASSERT_TRUE(image);
1942
1943 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1944 auto filtered =
1945 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(image));
1946
1947 // Define the entity that will serve as the control image as a Gaussian blur
1948 // filter with no filter at all.
1949 Entity entity_left;
1950 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1951 Matrix::MakeTranslation({100, 300}) *
1952 Matrix::MakeScale(Vector2{0.5, 0.5}));
1953 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1954 Sigma{0}, Sigma{0});
1955 entity_left.SetContents(unfiltered);
1956
1957 // Define the entity that will be filtered from sRGB to linear.
1958 Entity entity_right;
1959 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1960 Matrix::MakeTranslation({500, 300}) *
1961 Matrix::MakeScale(Vector2{0.5, 0.5}));
1962 entity_right.SetContents(filtered);
1963 return entity_left.Render(context, pass) &&
1964 entity_right.Render(context, pass);
1965 };
1966
1967 ASSERT_TRUE(OpenPlaygroundHere(callback));
1968 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilterCoverageIsCorrect |
| ) |  |

Definition at line 1918 of file entity_unittests.cc.

1918 {
1919 // Set up a simple color background.
1920 auto fill = std::make_shared<SolidColorContents>();
1921 fill->SetGeometry(Geometry::MakeFillPath(
1922 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1923 fill->SetColor(Color::DeepPink());
1924
1925 auto filter =
1926 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(fill));
1927
1928 Entity e;
1929 e.SetTransform(Matrix());
1930
1931 // Confirm that the actual filter coverage matches the expected coverage.
1932 auto actual = filter->GetCoverage(e);
1933 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1934
1935 ASSERT_TRUE(actual.has_value());
1936 ASSERT_RECT_NEAR(actual.value(), expected);
1937 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeCapAndJoinTest |
| ) |  |

Definition at line 339 of file entity_unittests.cc.

339 {
340 const Point padding(300, 250);
341 const Point margin(140, 180);
342
343 auto callback = [&](ContentContext& context, RenderPass& pass) {
344 // Slightly above sqrt(2) by default, so that right angles are just below
345 // the limit and acute angles are over the limit (causing them to get
346 // beveled).
347 static Scalar miter_limit = 1.41421357;
348 static Scalar width = 30;
349
350 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
351 {
352 ImGui::SliderFloat("Miter limit", &miter_limit, 0, 30);
353 ImGui::SliderFloat("Stroke width", &width, 0, 100);
354 if (ImGui::Button("Reset")) {
355 miter_limit = 1.41421357;
356 width = 30;
357 }
358 }
359 ImGui::End();
360
361 auto world_matrix = Matrix::MakeScale(GetContentScale());
362 auto render_path = [width = width, &context, &pass, &world_matrix](
363 const Path& path, Cap cap, Join join) {
364 auto contents = std::make_unique<SolidColorContents>();
365 contents->SetGeometry(Geometry::MakeStrokePath(path.Clone(), width,
366 miter_limit, cap, join));
367 contents->SetColor(Color::Red());
368
369 Entity entity;
370 entity.SetTransform(world_matrix);
371 entity.SetContents(std::move(contents));
372
373 auto coverage = entity.GetCoverage();
374 if (coverage.has_value()) {
375 auto bounds_contents = std::make_unique<SolidColorContents>();
376 bounds_contents->SetGeometry(Geometry::MakeFillPath(
377 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath()));
378 bounds_contents->SetColor(Color::Green().WithAlpha(0.5));
379 Entity bounds_entity;
380 bounds_entity.SetContents(std::move(bounds_contents));
381 bounds_entity.Render(context, pass);
382 }
383
384 entity.Render(context, pass);
385 };
386
387 const Point a_def(0, 0), b_def(0, 100), c_def(150, 0), d_def(150, -100),
388 e_def(75, 75);
389 const Scalar r = 30;
390 // Cap::kButt demo.
391 {
392 Point off = Point(0, 0) * padding + margin;
393 auto [a, b] = IMPELLER_PLAYGROUND_LINE(off + a_def, off + b_def, r,
394 Color::Black(), Color::White());
395 auto [c, d] = IMPELLER_PLAYGROUND_LINE(off + c_def, off + d_def, r,
396 Color::Black(), Color::White());
397 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
398 Cap::kButt, Join::kBevel);
399 }
400
401 // Cap::kSquare demo.
402 {
403 Point off = Point(1, 0) * padding + margin;
404 auto [a, b] = IMPELLER_PLAYGROUND_LINE(off + a_def, off + b_def, r,
405 Color::Black(), Color::White());
406 auto [c, d] = IMPELLER_PLAYGROUND_LINE(off + c_def, off + d_def, r,
407 Color::Black(), Color::White());
408 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
409 Cap::kSquare, Join::kBevel);
410 }
411
412 // Cap::kRound demo.
413 {
414 Point off = Point(2, 0) * padding + margin;
415 auto [a, b] = IMPELLER_PLAYGROUND_LINE(off + a_def, off + b_def, r,
416 Color::Black(), Color::White());
417 auto [c, d] = IMPELLER_PLAYGROUND_LINE(off + c_def, off + d_def, r,
418 Color::Black(), Color::White());
419 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
420 Cap::kRound, Join::kBevel);
421 }
422
423 // Join::kBevel demo.
424 {
425 Point off = Point(0, 1) * padding + margin;
426 Point a = IMPELLER_PLAYGROUND_POINT(off + a_def, r, Color::White());
427 Point b = IMPELLER_PLAYGROUND_POINT(off + e_def, r, Color::White());
428 Point c = IMPELLER_PLAYGROUND_POINT(off + c_def, r, Color::White());
429 render_path(
430 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
431 Cap::kButt, Join::kBevel);
432 }
433
434 // Join::kMiter demo.
435 {
436 Point off = Point(1, 1) * padding + margin;
437 Point a = IMPELLER_PLAYGROUND_POINT(off + a_def, r, Color::White());
438 Point b = IMPELLER_PLAYGROUND_POINT(off + e_def, r, Color::White());
439 Point c = IMPELLER_PLAYGROUND_POINT(off + c_def, r, Color::White());
440 render_path(
441 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
442 Cap::kButt, Join::kMiter);
443 }
444
445 // Join::kRound demo.
446 {
447 Point off = Point(2, 1) * padding + margin;
448 Point a = IMPELLER_PLAYGROUND_POINT(off + a_def, r, Color::White());
449 Point b = IMPELLER_PLAYGROUND_POINT(off + e_def, r, Color::White());
450 Point c = IMPELLER_PLAYGROUND_POINT(off + c_def, r, Color::White());
451 render_path(
452 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
453 Cap::kButt, Join::kRound);
454 }
455
456 return true;
457 };
458 ASSERT_TRUE(OpenPlaygroundHere(callback));
459 }

References impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddRect(), impeller::Color::Black(), impeller::Close(), impeller::Entity::GetCoverage(), impeller::Color::Green(), IMPELLER_PLAYGROUND_LINE, IMPELLER_PLAYGROUND_POINT, 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() [330/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeWithTextureContents |
| ) |  |

Definition at line 276 of file entity_unittests.cc.

276 {
277 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
278 Path path = PathBuilder{}
279 .MoveTo({100, 100})
280 .LineTo({100, 200})
281 .MoveTo({100, 300})
282 .LineTo({100, 400})
283 .MoveTo({100, 500})
284 .LineTo({100, 600})
285 .TakePath();
286
287 Entity entity;
288 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
289 auto contents = std::make_unique<TiledTextureContents>();
290 contents->SetGeometry(Geometry::MakeStrokePath(std::move(path), 100.0));
291 contents->SetTexture(bridge);
292 contents->SetTileModes(Entity::TileMode::kClamp, Entity::TileMode::kClamp);
293 entity.SetContents(std::move(contents));
294 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
295 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SweepGradientContentsIsOpaque |
| ) |  |

Definition at line 2382 of file entity_unittests.cc.

2382 {
2383 RadialGradientContents contents;
2384 contents.SetColors({Color::CornflowerBlue()});
2385 ASSERT_TRUE(contents.IsOpaque());
2386 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2387 ASSERT_FALSE(contents.IsOpaque());
2388 contents.SetColors({Color::CornflowerBlue()});
2389 contents.SetTileMode(Entity::TileMode::kDecal);
2390 ASSERT_FALSE(contents.IsOpaque());
2391 }

References impeller::Color::CornflowerBlue(), impeller::RadialGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::RadialGradientContents::SetColors(), impeller::RadialGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [332/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TextContentsCeilsGlyphScaleToDecimal |
| ) |  |

Definition at line 2454 of file entity_unittests.cc.

2454 {
2455 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.4321111f, 12), 0.43f);
2456 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.5321111f, 12), 0.53f);
2457 ASSERT_EQ(TextFrame::RoundScaledFontSize(2.1f, 12), 2.1f);
2458 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.0f, 12), 0.0f);
2459 }

References impeller::TextFrame::RoundScaledFontSize().

## ◆ TEST_P() [333/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ThreeStrokesInOnePath |
| ) |  |

Definition at line 257 of file entity_unittests.cc.

257 {
258 Path path = PathBuilder{}
259 .MoveTo({100, 100})
260 .LineTo({100, 200})
261 .MoveTo({100, 300})
262 .LineTo({100, 400})
263 .MoveTo({100, 500})
264 .LineTo({100, 600})
265 .TakePath();
266
267 Entity entity;
268 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
269 auto contents = std::make_unique<SolidColorContents>();
270 contents->SetGeometry(Geometry::MakeStrokePath(std::move(path), 5.0));
271 contents->SetColor(Color::Red());
272 entity.SetContents(std::move(contents));
273 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
274 }

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

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsIsOpaque |
| ) |  |

Definition at line 2393 of file entity_unittests.cc.

2393 {
2394 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
2395 TiledTextureContents contents;
2396 contents.SetTexture(bay_bridge);
2397 // This is a placeholder test. Images currently never decompress as opaque
2398 // (whether in Flutter or the playground), and so this should currently always
2399 // return false in practice.
2400 ASSERT_FALSE(contents.IsOpaque());
2401 }

References impeller::TiledTextureContents::IsOpaque(), and impeller::TiledTextureContents::SetTexture().

## ◆ TEST_P() [335/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsRendersWithCorrectPipeline |
| ) |  |

Definition at line 19 of file tiled_texture_contents_unittests.cc.

19 {
20 TextureDescriptor texture_desc;
21 texture_desc.size = {100, 100};
22 texture_desc.type = TextureType::kTexture2D;
23 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
24 texture_desc.storage_mode = StorageMode::kDevicePrivate;
25 auto texture =
26 GetContext()->GetResourceAllocator()->CreateTexture(texture_desc);
27
28 TiledTextureContents contents;
29 contents.SetTexture(texture);
30 contents.SetGeometry(Geometry::MakeCover());
31
32 auto content_context = GetContentContext();
33 auto buffer = content_context->GetContext()->CreateCommandBuffer();
34 auto render_target = RenderTarget::CreateOffscreenMSAA(
35 *content_context->GetContext(),
36 *GetContentContext()->GetRenderTargetCache(), {100, 100});
37 auto render_pass = buffer->CreateRenderPass(render_target);
38
39 ASSERT_TRUE(contents.Render(*GetContentContext(), {}, *render_pass));
40 const std::vector<Command>& commands = render_pass->GetCommands();
41
42 ASSERT_EQ(commands.size(), 1u);
43 ASSERT_STREQ(commands[0].pipeline->GetDescriptor().GetLabel().c_str(),
44 "TextureFill Pipeline V#1");
45 }

References impeller::RenderTarget::CreateOffscreenMSAA(), impeller::TextureDescriptor::format, impeller::kDevicePrivate, 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() [336/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsRendersWithCorrectPipelineExternalOES |
| ) |  |

Definition at line 49 of file tiled_texture_contents_unittests.cc.

49 {
50 if (GetParam() != PlaygroundBackend::kOpenGLES) {
51 GTEST_SKIP_(
52 "External OES textures are only valid for the OpenGLES backend.");
53 }
54
55 TextureDescriptor texture_desc;
56 texture_desc.size = {100, 100};
57 texture_desc.type = TextureType::kTextureExternalOES;
58 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
59 texture_desc.storage_mode = StorageMode::kDevicePrivate;
60 auto texture =
61 GetContext()->GetResourceAllocator()->CreateTexture(texture_desc);
62
63 TiledTextureContents contents;
64 contents.SetTexture(texture);
65 contents.SetGeometry(Geometry::MakeCover());
66
67 auto content_context = GetContentContext();
68 auto buffer = content_context->GetContext()->CreateCommandBuffer();
69 auto render_target = RenderTarget::CreateOffscreenMSAA(
70 *content_context->GetContext(),
71 *GetContentContext()->GetRenderTargetCache(), {100, 100});
72 auto render_pass = buffer->CreateRenderPass(render_target);
73
74 ASSERT_TRUE(contents.Render(*GetContentContext(), {}, *render_pass));
75 const std::vector<Command>& commands = render_pass->GetCommands();
76
77 ASSERT_EQ(commands.size(), 1u);
78 ASSERT_STREQ(commands[0].pipeline->GetDescriptor().GetLabel().c_str(),
79 "TextureFill Pipeline V#1");
80 }

References impeller::RenderTarget::CreateOffscreenMSAA(), 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() [337/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TriangleInsideASquare |
| ) |  |

Definition at line 297 of file entity_unittests.cc.

297 {
298 auto callback = [&](ContentContext& context, RenderPass& pass) {
299 Point offset(100, 100);
300
301 Point a =
302 IMPELLER_PLAYGROUND_POINT(Point(10, 10) + offset, 20, Color::White());
303 Point b =
304 IMPELLER_PLAYGROUND_POINT(Point(210, 10) + offset, 20, Color::White());
305 Point c =
306 IMPELLER_PLAYGROUND_POINT(Point(210, 210) + offset, 20, Color::White());
307 Point d =
308 IMPELLER_PLAYGROUND_POINT(Point(10, 210) + offset, 20, Color::White());
309 Point e =
310 IMPELLER_PLAYGROUND_POINT(Point(50, 50) + offset, 20, Color::White());
311 Point f =
312 IMPELLER_PLAYGROUND_POINT(Point(100, 50) + offset, 20, Color::White());
313 Point g =
314 IMPELLER_PLAYGROUND_POINT(Point(50, 150) + offset, 20, Color::White());
315 Path path = PathBuilder{}
316 .MoveTo(a)
317 .LineTo(b)
318 .LineTo(c)
319 .LineTo(d)
320 .Close()
321 .MoveTo(e)
322 .LineTo(f)
323 .LineTo(g)
324 .Close()
325 .TakePath();
326
327 Entity entity;
328 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
329 auto contents = std::make_unique<SolidColorContents>();
330 contents->SetGeometry(Geometry::MakeStrokePath(std::move(path), 20.0));
331 contents->SetColor(Color::Red());
332 entity.SetContents(std::move(contents));
333
334 return entity.Render(context, pass);
335 };
336 ASSERT_TRUE(OpenPlaygroundHere(callback));
337 }

References impeller::PathBuilder::Close(), IMPELLER_PLAYGROUND_POINT, impeller::PathBuilder::LineTo(), 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() [338/384]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | YUVToRGBFilter |
| ) |  |

Definition at line 2101 of file entity_unittests.cc.

2101 {
2102 if (GetParam() == PlaygroundBackend::kOpenGLES) {
2103 // TODO(114588) : Support YUV to RGB filter on OpenGLES backend.
2104 GTEST_SKIP_("YUV to RGB filter is not supported on OpenGLES backend yet.");
2105 }
2106
2107 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2108 YUVColorSpace yuv_color_space_array[2]{YUVColorSpace::kBT601FullRange,
2109 YUVColorSpace::kBT601LimitedRange};
2110 for (int i = 0; i < 2; i++) {
2111 auto yuv_color_space = yuv_color_space_array[i];
2112 auto textures =
2113 CreateTestYUVTextures(GetContext().get(), yuv_color_space);
2114 auto filter_contents = FilterContents::MakeYUVToRGBFilter(
2115 textures[0], textures[1], yuv_color_space);
2116 Entity filter_entity;
2117 filter_entity.SetContents(filter_contents);
2118 auto snapshot = filter_contents->RenderToSnapshot(context, filter_entity);
2119
2120 Entity entity;
2121 auto contents = TextureContents::MakeRect(Rect::MakeLTRB(0, 0, 256, 256));
2122 contents->SetTexture(snapshot->texture);
2123 contents->SetSourceRect(Rect::MakeSize(snapshot->texture->GetSize()));
2124 entity.SetContents(contents);
2125 entity.SetTransform(
2126 Matrix::MakeTranslation({static_cast<Scalar>(100 + 400 * i), 300}));
2127 entity.Render(context, pass);
2128 }
2129 return true;
2130 };
2131 ASSERT_TRUE(OpenPlaygroundHere(callback));
2132 }

References CreateTestYUVTextures(), impeller::kBT601FullRange, impeller::kBT601LimitedRange, impeller::kOpenGLES, impeller::TRect< Scalar >::MakeLTRB(), impeller::TextureContents::MakeRect(), impeller::TRect< Scalar >::MakeSize(), impeller::Matrix::MakeTranslation(), impeller::FilterContents::MakeYUVToRGBFilter(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [339/384]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CalculateUVsSimple |
| ) |  |

Definition at line 279 of file gaussian_blur_filter_contents_unittests.cc.

279 {
280 TextureDescriptor desc = {
281 .storage_mode = StorageMode::kDevicePrivate,
282 .format = PixelFormat::kB8G8R8A8UNormInt,
283 .size = ISize(100, 100),
284 };
285 std::shared_ptr<Texture> texture = MakeTexture(desc);
286 auto filter_input = FilterInput::Make(texture);
287 Entity entity;
288 Quad uvs = GaussianBlurFilterContents::CalculateUVs(
289 filter_input, entity, Rect::MakeSize(ISize(100, 100)), ISize(100, 100));
290 std::optional<Rect> uvs_bounds = Rect::MakePointBounds(uvs);
291 EXPECT_TRUE(uvs_bounds.has_value());
292 if (uvs_bounds.has_value()) {
293 EXPECT_TRUE(RectNear(uvs_bounds.value(), Rect::MakeXYWH(0, 0, 1, 1)));
294 }
295 }

References impeller::GaussianBlurFilterContents::CalculateUVs(), impeller::kB8G8R8A8UNormInt, impeller::kDevicePrivate, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakePointBounds(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), RectNear(), and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [340/384]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageWithEffectTransform |
| ) |  |

Definition at line 132 of file gaussian_blur_filter_contents_unittests.cc.

132 {
133 TextureDescriptor desc = {
134 .storage_mode = StorageMode::kDevicePrivate,
135 .format = PixelFormat::kB8G8R8A8UNormInt,
136 .size = ISize(100, 100),
137 };
138 Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
139 GaussianBlurFilterContents contents(/*sigma_x=*/sigma_radius_1,
140 /*sigma_y=*/sigma_radius_1,
141 Entity::TileMode::kDecal);
142 std::shared_ptr<Texture> texture =
143 GetContentContext()->GetContext()->GetResourceAllocator()->CreateTexture(
144 desc);
145 FilterInput::Vector inputs = {FilterInput::Make(texture)};
146 Entity entity;
147 entity.SetTransform(Matrix::MakeTranslation({100, 100, 0}));
148 std::optional<Rect> coverage = contents.GetFilterCoverage(
149 inputs, entity, /*effect_transform=*/Matrix::MakeScale({2.0, 2.0, 1.0}));
150 EXPECT_TRUE(coverage.has_value());
151 if (coverage.has_value()) {
152 EXPECT_RECT_NEAR(coverage.value(),
153 Rect::MakeLTRB(100 - 2, 100 - 2, 200 + 2, 200 + 2));
154 }
155 }

References EXPECT_RECT_NEAR, impeller::GaussianBlurFilterContents::GetFilterCoverage(), impeller::kB8G8R8A8UNormInt, impeller::Entity::kDecal, impeller::kDevicePrivate, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetTransform(), and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [341/384]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageWithTexture |
| ) |  |

Definition at line 108 of file gaussian_blur_filter_contents_unittests.cc.

108 {
109 TextureDescriptor desc = {
110 .storage_mode = StorageMode::kDevicePrivate,
111 .format = PixelFormat::kB8G8R8A8UNormInt,
112 .size = ISize(100, 100),
113 };
114 Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
115 GaussianBlurFilterContents contents(/*sigma_X=*/sigma_radius_1,
116 /*sigma_y=*/sigma_radius_1,
117 Entity::TileMode::kDecal);
118 std::shared_ptr<Texture> texture =
119 GetContentContext()->GetContext()->GetResourceAllocator()->CreateTexture(
120 desc);
121 FilterInput::Vector inputs = {FilterInput::Make(texture)};
122 Entity entity;
123 entity.SetTransform(Matrix::MakeTranslation({100, 100, 0}));
124 std::optional<Rect> coverage =
125 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
126 EXPECT_TRUE(coverage.has_value());
127 if (coverage.has_value()) {
128 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(99, 99, 201, 201));
129 }
130 }

References EXPECT_RECT_NEAR, impeller::GaussianBlurFilterContents::GetFilterCoverage(), impeller::kB8G8R8A8UNormInt, impeller::Entity::kDecal, impeller::kDevicePrivate, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetTransform(), and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [342/384]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverage |
| ) |  |

Definition at line 176 of file gaussian_blur_filter_contents_unittests.cc.

176 {
177 TextureDescriptor desc = {
178 .storage_mode = StorageMode::kDevicePrivate,
179 .format = PixelFormat::kB8G8R8A8UNormInt,
180 .size = ISize(100, 100),
181 };
182 std::shared_ptr<Texture> texture = MakeTexture(desc);
183 Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
184 auto contents = std::make_unique<GaussianBlurFilterContents>(
185 sigma_radius_1, sigma_radius_1, Entity::TileMode::kDecal);
186 contents->SetInputs({FilterInput::Make(texture)});
187 std::shared_ptr<ContentContext> renderer = GetContentContext();
188
189 Entity entity;
190 std::optional<Entity> result =
191 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
192 EXPECT_TRUE(result.has_value());
193 if (result.has_value()) {
194 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
195 std::optional<Rect> result_coverage = result.value().GetCoverage();
196 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
197 EXPECT_TRUE(result_coverage.has_value());
198 EXPECT_TRUE(contents_coverage.has_value());
199 if (result_coverage.has_value() && contents_coverage.has_value()) {
200 EXPECT_TRUE(RectNear(contents_coverage.value(),
201 Rect::MakeLTRB(-1, -1, 101, 101)));
202 EXPECT_TRUE(
203 RectNear(result_coverage.value(), Rect::MakeLTRB(-1, -1, 101, 101)));
204 }
205 }
206 }

References impeller::kB8G8R8A8UNormInt, impeller::Entity::kDecal, impeller::kDevicePrivate, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), RectNear(), and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [343/384]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageRotated |
| ) |  |

Definition at line 243 of file gaussian_blur_filter_contents_unittests.cc.

244 {
245 TextureDescriptor desc = {
246 .storage_mode = StorageMode::kDevicePrivate,
247 .format = PixelFormat::kB8G8R8A8UNormInt,
248 .size = ISize(400, 300),
249 };
250 std::shared_ptr<Texture> texture = MakeTexture(desc);
251 Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
252 auto contents = std::make_unique<GaussianBlurFilterContents>(
253 sigma_radius_1, sigma_radius_1, Entity::TileMode::kDecal);
254 contents->SetInputs({FilterInput::Make(texture)});
255 std::shared_ptr<ContentContext> renderer = GetContentContext();
256
257 Entity entity;
258 // Rotate around the top left corner, then push it over to (100, 100).
259 entity.SetTransform(Matrix::MakeTranslation({400, 100, 0}) *
260 Matrix::MakeRotationZ(Degrees(90.0)));
261 std::optional<Entity> result =
262 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
263 EXPECT_TRUE(result.has_value());
264 if (result.has_value()) {
265 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
266 std::optional<Rect> result_coverage = result.value().GetCoverage();
267 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
268 EXPECT_TRUE(result_coverage.has_value());
269 EXPECT_TRUE(contents_coverage.has_value());
270 if (result_coverage.has_value() && contents_coverage.has_value()) {
271 EXPECT_TRUE(RectNear(contents_coverage.value(),
272 Rect::MakeLTRB(99, 99, 401, 501)));
273 EXPECT_TRUE(
274 RectNear(result_coverage.value(), Rect::MakeLTRB(99, 99, 401, 501)));
275 }
276 }
277 }

References impeller::kB8G8R8A8UNormInt, impeller::Entity::kDecal, impeller::kDevicePrivate, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeTranslation(), RectNear(), impeller::Entity::SetTransform(), and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [344/384]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageTranslate |
| ) |  |

Definition at line 208 of file gaussian_blur_filter_contents_unittests.cc.

209 {
210 TextureDescriptor desc = {
211 .storage_mode = StorageMode::kDevicePrivate,
212 .format = PixelFormat::kB8G8R8A8UNormInt,
213 .size = ISize(100, 100),
214 };
215 std::shared_ptr<Texture> texture = MakeTexture(desc);
216 Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
217 auto contents = std::make_unique<GaussianBlurFilterContents>(
218 sigma_radius_1, sigma_radius_1, Entity::TileMode::kDecal);
219 contents->SetInputs({FilterInput::Make(texture)});
220 std::shared_ptr<ContentContext> renderer = GetContentContext();
221
222 Entity entity;
223 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
224 std::optional<Entity> result =
225 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
226
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(99, 199, 201, 301)));
237 EXPECT_TRUE(
238 RectNear(result_coverage.value(), Rect::MakeLTRB(99, 199, 201, 301)));
239 }
240 }
241 }

References impeller::kB8G8R8A8UNormInt, impeller::Entity::kDecal, impeller::kDevicePrivate, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), RectNear(), impeller::Entity::SetTransform(), and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [345/384]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithDestinationRect |
| ) |  |

Definition at line 297 of file gaussian_blur_filter_contents_unittests.cc.

297 {
298 TextureDescriptor desc = {
299 .storage_mode = StorageMode::kDevicePrivate,
300 .format = PixelFormat::kB8G8R8A8UNormInt,
301 .size = ISize(100, 100),
302 };
303
304 std::shared_ptr<Texture> texture = MakeTexture(desc);
305 auto texture_contents = std::make_shared<TextureContents>();
306 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
307 texture_contents->SetTexture(texture);
308 texture_contents->SetDestinationRect(Rect::MakeXYWH(
309 50, 40, texture->GetSize().width, texture->GetSize().height));
310
311 Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
312 auto contents = std::make_unique<GaussianBlurFilterContents>(
313 sigma_radius_1, sigma_radius_1, Entity::TileMode::kDecal);
314 contents->SetInputs({FilterInput::Make(texture_contents)});
315 std::shared_ptr<ContentContext> renderer = GetContentContext();
316
317 Entity entity;
318 std::optional<Entity> result =
319 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
320 EXPECT_TRUE(result.has_value());
321 if (result.has_value()) {
322 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
323 std::optional<Rect> result_coverage = result.value().GetCoverage();
324 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
325 EXPECT_TRUE(result_coverage.has_value());
326 EXPECT_TRUE(contents_coverage.has_value());
327 if (result_coverage.has_value() && contents_coverage.has_value()) {
328 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
329 EXPECT_TRUE(RectNear(result_coverage.value(),
330 Rect::MakeLTRB(49.f, 39.f, 151.f, 141.f)));
331 }
332 }
333 }

References impeller::kB8G8R8A8UNormInt, impeller::Entity::kDecal, impeller::kDevicePrivate, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), RectNear(), and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [346/384]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithDestinationRectScaled |
| ) |  |

Definition at line 335 of file gaussian_blur_filter_contents_unittests.cc.

336 {
337 TextureDescriptor desc = {
338 .storage_mode = StorageMode::kDevicePrivate,
339 .format = PixelFormat::kB8G8R8A8UNormInt,
340 .size = ISize(100, 100),
341 };
342
343 std::shared_ptr<Texture> texture = MakeTexture(desc);
344 auto texture_contents = std::make_shared<TextureContents>();
345 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
346 texture_contents->SetTexture(texture);
347 texture_contents->SetDestinationRect(Rect::MakeXYWH(
348 50, 40, texture->GetSize().width, texture->GetSize().height));
349
350 Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
351 auto contents = std::make_unique<GaussianBlurFilterContents>(
352 sigma_radius_1, sigma_radius_1, Entity::TileMode::kDecal);
353 contents->SetInputs({FilterInput::Make(texture_contents)});
354 std::shared_ptr<ContentContext> renderer = GetContentContext();
355
356 Entity entity;
357 entity.SetTransform(Matrix::MakeScale({2.0, 2.0, 1.0}));
358 std::optional<Entity> result =
359 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
360 EXPECT_TRUE(result.has_value());
361 if (result.has_value()) {
362 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
363 std::optional<Rect> result_coverage = result.value().GetCoverage();
364 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
365 EXPECT_TRUE(result_coverage.has_value());
366 EXPECT_TRUE(contents_coverage.has_value());
367 if (result_coverage.has_value() && contents_coverage.has_value()) {
368 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
369 EXPECT_TRUE(RectNear(contents_coverage.value(),
370 Rect::MakeLTRB(98.f, 78.f, 302.f, 282.f)));
371 }
372 }
373 }

References impeller::kB8G8R8A8UNormInt, impeller::Entity::kDecal, impeller::kDevicePrivate, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), RectNear(), impeller::Entity::SetTransform(), and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [347/384]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanInstantiateFlutterGPUContext |
| ) |  |

Definition at line 107 of file renderer_dart_unittests.cc.

107 {
108 auto isolate = GetIsolate();
109 bool result = isolate->RunInIsolateScope([]() -> bool {
110 if (tonic::CheckAndHandleError(::Dart_Invoke(
111 Dart_RootLibrary(), tonic::ToDart("instantiateDefaultContext"), 0,
112 nullptr))) {
113 return false;
114 }
115 return true;
116 });
117
118 ASSERT_TRUE(result);
119 }

## ◆ TEST_P() [348/384]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanRunDartInPlaygroundFrame |
| ) |  |

Definition at line 87 of file renderer_dart_unittests.cc.

87 {
88 auto isolate = GetIsolate();
89
90 SinglePassCallback callback = [&](RenderPass& pass) {
91 ImGui::Begin("Dart test", nullptr);
92 ImGui::Text(
93 "This test executes Dart code during the playground frame callback.");
94 ImGui::End();
95
96 return isolate->RunInIsolateScope([]() -> bool {
97 if (tonic::CheckAndHandleError(::Dart_Invoke(
98 Dart_RootLibrary(), tonic::ToDart("sayHi"), 0, nullptr))) {
99 return false;
100 }
101 return true;
102 });
103 };
104 OpenPlaygroundHere(callback);
105 }

## ◆ TEST_P() [349/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | ArrayUniforms |
| ) |  |

Definition at line 884 of file renderer_unittests.cc.

884 {
885 using VS = ArrayVertexShader;
886 using FS = ArrayFragmentShader;
887
888 auto context = GetContext();
889 auto pipeline_descriptor =
890 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
891 ASSERT_TRUE(pipeline_descriptor.has_value());
892 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
893 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
894 auto pipeline =
895 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
896 ASSERT_TRUE(pipeline && pipeline->IsValid());
897
898 SinglePassCallback callback = [&](RenderPass& pass) {
899 auto size = pass.GetRenderTargetSize();
900
901 Command cmd;
902 cmd.pipeline = pipeline;
903 DEBUG_COMMAND_INFO(cmd, "Google Dots");
904 VertexBufferBuilder<VS::PerVertexData> builder;
905 builder.AddVertices({{Point()},
906 {Point(0, size.height)},
907 {Point(size.width, 0)},
908 {Point(size.width, 0)},
909 {Point(0, size.height)},
910 {Point(size.width, size.height)}});
911 cmd.BindVertices(builder.CreateVertexBuffer(pass.GetTransientsBuffer()));
912
913 VS::FrameInfo frame_info;
914 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
915 frame_info.mvp =
916 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
917 VS::BindFrameInfo(cmd,
918 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
919
920 auto time = GetSecondsElapsed();
921 auto y_pos = [&time](float x) {
922 return 400 + 10 * std::cos(time * 5 + x / 6);
923 };
924
925 FS::FragInfo fs_uniform = {
926 .circle_positions = {Point(430, y_pos(0)), Point(480, y_pos(1)),
927 Point(530, y_pos(2)), Point(580, y_pos(3))},
928 .colors = {Color::MakeRGBA8(66, 133, 244, 255),
929 Color::MakeRGBA8(219, 68, 55, 255),
930 Color::MakeRGBA8(244, 180, 0, 255),
931 Color::MakeRGBA8(15, 157, 88, 255)},
932 };
933 FS::BindFragInfo(cmd,
934 pass.GetTransientsBuffer().EmplaceUniform(fs_uniform));
935
936 pass.AddCommand(std::move(cmd));
937 return true;
938 };
939 OpenPlaygroundHere(callback);
940 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::kCount4, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Color::MakeRGBA8(), impeller::Matrix::MakeScale(), and impeller::Command::pipeline.

## ◆ TEST_P() [350/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToBuffer |
| ) |  |

Definition at line 569 of file renderer_unittests.cc.

569 {
570 auto context = GetContext();
571 ASSERT_TRUE(context);
572
573 using VS = MipmapsVertexShader;
574 using FS = MipmapsFragmentShader;
575 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
576 ASSERT_TRUE(desc.has_value());
577 desc->SetSampleCount(SampleCount::kCount4);
578 desc->SetStencilAttachmentDescriptors(std::nullopt);
579 auto mipmaps_pipeline =
580 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
581 ASSERT_TRUE(mipmaps_pipeline);
582
583 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
584 auto boston = CreateTextureForFixture("boston.jpg");
585 ASSERT_TRUE(bridge && boston);
586 auto sampler = context->GetSamplerLibrary()->GetSampler({});
587 ASSERT_TRUE(sampler);
588
589 TextureDescriptor texture_desc;
590 texture_desc.storage_mode = StorageMode::kHostVisible;
591 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
592 texture_desc.size = bridge->GetTextureDescriptor().size;
593 texture_desc.mip_count = 1u;
594 texture_desc.usage =
595 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget) |
596 static_cast<TextureUsageMask>(TextureUsage::kShaderWrite) |
597 static_cast<TextureUsageMask>(TextureUsage::kShaderRead);
598 DeviceBufferDescriptor device_buffer_desc;
599 device_buffer_desc.storage_mode = StorageMode::kHostVisible;
600 device_buffer_desc.size =
601 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
602 auto device_buffer =
603 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
604
605 // Vertex buffer.
606 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
607 vertex_builder.SetLabel("Box");
608 auto size = Point(boston->GetSize());
609 vertex_builder.AddVertices({
610 {{0, 0}, {0.0, 0.0}}, // 1
611 {{size.x, 0}, {1.0, 0.0}}, // 2
612 {{size.x, size.y}, {1.0, 1.0}}, // 3
613 {{0, 0}, {0.0, 0.0}}, // 1
614 {{size.x, size.y}, {1.0, 1.0}}, // 3
615 {{0, size.y}, {0.0, 1.0}}, // 4
616 });
617 auto vertex_buffer =
618 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
619 ASSERT_TRUE(vertex_buffer);
620
621 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
622 {
623 auto buffer = context->CreateCommandBuffer();
624 if (!buffer) {
625 return false;
626 }
627 buffer->SetLabel("Playground Command Buffer");
628 auto pass = buffer->CreateBlitPass();
629 if (!pass) {
630 return false;
631 }
632 pass->SetLabel("Playground Blit Pass");
633
634 if (render_target.GetColorAttachments().empty()) {
635 return false;
636 }
637
638 // Blit `bridge` to the top left corner of the texture.
639 pass->AddCopy(bridge, device_buffer);
640
641 pass->EncodeCommands(context->GetResourceAllocator());
642
643 if (!buffer->SubmitCommands()) {
644 return false;
645 }
646 }
647
648 {
649 auto buffer = context->CreateCommandBuffer();
650 if (!buffer) {
651 return false;
652 }
653 buffer->SetLabel("Playground Command Buffer");
654
655 auto pass = buffer->CreateRenderPass(render_target);
656 if (!pass) {
657 return false;
658 }
659 pass->SetLabel("Playground Render Pass");
660 {
661 Command cmd;
662 DEBUG_COMMAND_INFO(cmd, "Image");
663 cmd.pipeline = mipmaps_pipeline;
664
665 cmd.BindVertices(vertex_buffer);
666
667 VS::FrameInfo frame_info;
668 EXPECT_EQ(pass->GetOrthographicTransform(),
669 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
670 frame_info.mvp = pass->GetOrthographicTransform() *
671 Matrix::MakeScale(GetContentScale());
672 VS::BindFrameInfo(
673 cmd, pass->GetTransientsBuffer().EmplaceUniform(frame_info));
674
675 FS::FragInfo frag_info;
676 frag_info.lod = 0;
677 FS::BindFragInfo(cmd,
678 pass->GetTransientsBuffer().EmplaceUniform(frag_info));
679
680 auto sampler = context->GetSamplerLibrary()->GetSampler({});
681 auto buffer_view = device_buffer->AsBufferView();
682 auto texture =
683 context->GetResourceAllocator()->CreateTexture(texture_desc);
684 if (!texture->SetContents(buffer_view.contents,
685 buffer_view.range.length)) {
686 VALIDATION_LOG << "Could not upload texture to device memory";
687 return false;
688 }
689 FS::BindTex(cmd, texture, sampler);
690
691 pass->AddCommand(std::move(cmd));
692 }
693 pass->EncodeCommands();
694 if (!buffer->SubmitCommands()) {
695 return false;
696 }
697 }
698 return true;
699 };
700 OpenPlaygroundHere(callback);
701 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::TextureDescriptor::format, impeller::kCount4, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::kRenderTarget, impeller::kShaderRead, impeller::kShaderWrite, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::TextureDescriptor::mip_count, impeller::Command::pipeline, 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() [351/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToTexture |
| ) |  |

Definition at line 454 of file renderer_unittests.cc.

454 {
455 auto context = GetContext();
456 ASSERT_TRUE(context);
457
458 using VS = MipmapsVertexShader;
459 using FS = MipmapsFragmentShader;
460 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
461 ASSERT_TRUE(desc.has_value());
462 desc->SetSampleCount(SampleCount::kCount4);
463 desc->SetStencilAttachmentDescriptors(std::nullopt);
464 auto mipmaps_pipeline =
465 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
466 ASSERT_TRUE(mipmaps_pipeline);
467
468 TextureDescriptor texture_desc;
469 texture_desc.storage_mode = StorageMode::kHostVisible;
470 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
471 texture_desc.size = {800, 600};
472 texture_desc.mip_count = 1u;
473 texture_desc.usage =
474 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget) |
475 static_cast<TextureUsageMask>(TextureUsage::kShaderRead);
476 auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
477 ASSERT_TRUE(texture);
478
479 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
480 auto boston = CreateTextureForFixture("boston.jpg");
481 ASSERT_TRUE(bridge && boston);
482 auto sampler = context->GetSamplerLibrary()->GetSampler({});
483 ASSERT_TRUE(sampler);
484
485 // Vertex buffer.
486 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
487 vertex_builder.SetLabel("Box");
488 auto size = Point(boston->GetSize());
489 vertex_builder.AddVertices({
490 {{0, 0}, {0.0, 0.0}}, // 1
491 {{size.x, 0}, {1.0, 0.0}}, // 2
492 {{size.x, size.y}, {1.0, 1.0}}, // 3
493 {{0, 0}, {0.0, 0.0}}, // 1
494 {{size.x, size.y}, {1.0, 1.0}}, // 3
495 {{0, size.y}, {0.0, 1.0}}, // 4
496 });
497 auto vertex_buffer =
498 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
499 ASSERT_TRUE(vertex_buffer);
500
501 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
502 auto buffer = context->CreateCommandBuffer();
503 if (!buffer) {
504 return false;
505 }
506 buffer->SetLabel("Playground Command Buffer");
507
508 {
509 auto pass = buffer->CreateBlitPass();
510 if (!pass) {
511 return false;
512 }
513 pass->SetLabel("Playground Blit Pass");
514
515 if (render_target.GetColorAttachments().empty()) {
516 return false;
517 }
518
519 // Blit `bridge` to the top left corner of the texture.
520 pass->AddCopy(bridge, texture);
521
522 if (!pass->EncodeCommands(context->GetResourceAllocator())) {
523 return false;
524 }
525 }
526
527 {
528 auto pass = buffer->CreateRenderPass(render_target);
529 if (!pass) {
530 return false;
531 }
532 pass->SetLabel("Playground Render Pass");
533 {
534 Command cmd;
535 DEBUG_COMMAND_INFO(cmd, "Image");
536 cmd.pipeline = mipmaps_pipeline;
537
538 cmd.BindVertices(vertex_buffer);
539
540 VS::FrameInfo frame_info;
541 EXPECT_EQ(pass->GetOrthographicTransform(),
542 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
543 frame_info.mvp = pass->GetOrthographicTransform() *
544 Matrix::MakeScale(GetContentScale());
545 VS::BindFrameInfo(
546 cmd, pass->GetTransientsBuffer().EmplaceUniform(frame_info));
547
548 FS::FragInfo frag_info;
549 frag_info.lod = 0;
550 FS::BindFragInfo(cmd,
551 pass->GetTransientsBuffer().EmplaceUniform(frag_info));
552
553 auto sampler = context->GetSamplerLibrary()->GetSampler({});
554 FS::BindTex(cmd, texture, sampler);
555
556 pass->AddCommand(std::move(cmd));
557 }
558 pass->EncodeCommands();
559 }
560
561 if (!buffer->SubmitCommands()) {
562 return false;
563 }
564 return true;
565 };
566 OpenPlaygroundHere(callback);
567 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::TextureDescriptor::format, impeller::kCount4, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::kRenderTarget, impeller::kShaderRead, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::TextureDescriptor::mip_count, impeller::Command::pipeline, impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::usage.

## ◆ TEST_P() [352/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanCreateBoxPrimitive |
| ) |  |

Definition at line 46 of file renderer_unittests.cc.

46 {
47 using VS = BoxFadeVertexShader;
48 using FS = BoxFadeFragmentShader;
49 auto context = GetContext();
50 ASSERT_TRUE(context);
51 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
52 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
53 ASSERT_TRUE(desc.has_value());
54 desc->SetSampleCount(SampleCount::kCount4);
55 desc->SetStencilAttachmentDescriptors(std::nullopt);
56
57 // Vertex buffer.
58 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
59 vertex_builder.SetLabel("Box");
60 vertex_builder.AddVertices({
61 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
62 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
63 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
64 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
65 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
66 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
67 });
68 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
69 auto boston = CreateTextureForFixture("boston.jpg");
70 ASSERT_TRUE(bridge && boston);
71 auto sampler = context->GetSamplerLibrary()->GetSampler({});
72 ASSERT_TRUE(sampler);
73 SinglePassCallback callback = [&](RenderPass& pass) {
74 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
75 static bool wireframe;
76 ImGui::Checkbox("Wireframe", &wireframe);
77 ImGui::End();
78
79 desc->SetPolygonMode(wireframe ? PolygonMode::kLine : PolygonMode::kFill);
80 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
81
82 assert(pipeline && pipeline->IsValid());
83
84 Command cmd;
85 DEBUG_COMMAND_INFO(cmd, "Box");
86 cmd.pipeline = pipeline;
87
88 cmd.BindVertices(
89 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator()));
90
91 VS::UniformBuffer uniforms;
92 EXPECT_EQ(pass.GetOrthographicTransform(),
93 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
94 uniforms.mvp =
95 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
96 VS::BindUniformBuffer(cmd,
97 pass.GetTransientsBuffer().EmplaceUniform(uniforms));
98
99 FS::FrameInfo frame_info;
100 frame_info.current_time = GetSecondsElapsed();
101 frame_info.cursor_position = GetCursorPosition();
102 frame_info.window_size.x = GetWindowSize().width;
103 frame_info.window_size.y = GetWindowSize().height;
104
105 FS::BindFrameInfo(cmd,
106 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
107 FS::BindContents1(cmd, boston, sampler);
108 FS::BindContents2(cmd, bridge, sampler);
109 if (!pass.AddCommand(std::move(cmd))) {
110 return false;
111 }
112 return true;
113 };
114 OpenPlaygroundHere(callback);
115 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::kCount4, impeller::kFill, impeller::kLine, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::Command::pipeline, and impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel().

## ◆ TEST_P() [353/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanCreateCPUBackedTexture |
| ) |  |

Definition at line 989 of file renderer_unittests.cc.

989 {
990 if (GetParam() == PlaygroundBackend::kOpenGLES) {
991 GTEST_SKIP_("CPU backed textures are not supported on OpenGLES.");
992 }
993
994 auto context = GetContext();
995 auto allocator = context->GetResourceAllocator();
996 size_t dimension = 2;
997
998 do {
999 ISize size(dimension, dimension);
1000 TextureDescriptor texture_descriptor;
1001 texture_descriptor.storage_mode = StorageMode::kHostVisible;
1002 texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
1003 texture_descriptor.size = size;
1004 auto row_bytes =
1005 std::max(static_cast<uint16_t>(size.width * 4),
1006 allocator->MinimumBytesPerRow(texture_descriptor.format));
1007 auto buffer_size = size.height * row_bytes;
1008
1009 DeviceBufferDescriptor buffer_descriptor;
1010 buffer_descriptor.storage_mode = StorageMode::kHostVisible;
1011 buffer_descriptor.size = buffer_size;
1012
1013 auto buffer = allocator->CreateBuffer(buffer_descriptor);
1014
1015 ASSERT_TRUE(buffer);
1016
1017 auto texture = buffer->AsTexture(*allocator, texture_descriptor, row_bytes);
1018
1019 ASSERT_TRUE(texture);
1020 ASSERT_TRUE(texture->IsValid());
1021
1022 dimension *= 2;
1023 } while (dimension <= 8192);
1024 }

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

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanGenerateMipmaps |
| ) |  |

Definition at line 703 of file renderer_unittests.cc.

703 {
704 auto context = GetContext();
705 ASSERT_TRUE(context);
706
707 using VS = MipmapsVertexShader;
708 using FS = MipmapsFragmentShader;
709 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
710 ASSERT_TRUE(desc.has_value());
711 desc->SetSampleCount(SampleCount::kCount4);
712 desc->SetStencilAttachmentDescriptors(std::nullopt);
713 auto mipmaps_pipeline =
714 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
715 ASSERT_TRUE(mipmaps_pipeline);
716
717 auto boston = CreateTextureForFixture("boston.jpg", true);
718 ASSERT_TRUE(boston);
719
720 // Vertex buffer.
721 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
722 vertex_builder.SetLabel("Box");
723 auto size = Point(boston->GetSize());
724 vertex_builder.AddVertices({
725 {{0, 0}, {0.0, 0.0}}, // 1
726 {{size.x, 0}, {1.0, 0.0}}, // 2
727 {{size.x, size.y}, {1.0, 1.0}}, // 3
728 {{0, 0}, {0.0, 0.0}}, // 1
729 {{size.x, size.y}, {1.0, 1.0}}, // 3
730 {{0, size.y}, {0.0, 1.0}}, // 4
731 });
732 auto vertex_buffer =
733 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
734 ASSERT_TRUE(vertex_buffer);
735
736 bool first_frame = true;
737 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
738 const char* mip_filter_names[] = {"Nearest", "Linear"};
739 const MipFilter mip_filters[] = {MipFilter::kNearest, MipFilter::kLinear};
740 const char* min_filter_names[] = {"Nearest", "Linear"};
741 const MinMagFilter min_filters[] = {MinMagFilter::kNearest,
742 MinMagFilter::kLinear};
743
744 // UI state.
745 static int selected_mip_filter = 1;
746 static int selected_min_filter = 0;
747 static float lod = 4.5;
748
749 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
750 ImGui::Combo("Mip filter", &selected_mip_filter, mip_filter_names,
751 sizeof(mip_filter_names) / sizeof(char*));
752 ImGui::Combo("Min filter", &selected_min_filter, min_filter_names,
753 sizeof(min_filter_names) / sizeof(char*));
754 ImGui::SliderFloat("LOD", &lod, 0, boston->GetMipCount() - 1);
755 ImGui::End();
756
757 auto buffer = context->CreateCommandBuffer();
758 if (!buffer) {
759 return false;
760 }
761 buffer->SetLabel("Playground Command Buffer");
762
763 if (first_frame) {
764 auto pass = buffer->CreateBlitPass();
765 if (!pass) {
766 return false;
767 }
768 pass->SetLabel("Playground Blit Pass");
769
770 pass->GenerateMipmap(boston, "Boston Mipmap");
771
772 pass->EncodeCommands(context->GetResourceAllocator());
773 }
774
775 first_frame = false;
776
777 {
778 auto pass = buffer->CreateRenderPass(render_target);
779 if (!pass) {
780 return false;
781 }
782 pass->SetLabel("Playground Render Pass");
783 {
784 Command cmd;
785 DEBUG_COMMAND_INFO(cmd, "Image LOD");
786 cmd.pipeline = mipmaps_pipeline;
787
788 cmd.BindVertices(vertex_buffer);
789
790 VS::FrameInfo frame_info;
791 EXPECT_EQ(pass->GetOrthographicTransform(),
792 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
793 frame_info.mvp = pass->GetOrthographicTransform() *
794 Matrix::MakeScale(GetContentScale());
795 VS::BindFrameInfo(
796 cmd, pass->GetTransientsBuffer().EmplaceUniform(frame_info));
797
798 FS::FragInfo frag_info;
799 frag_info.lod = lod;
800 FS::BindFragInfo(cmd,
801 pass->GetTransientsBuffer().EmplaceUniform(frag_info));
802
803 SamplerDescriptor sampler_desc;
804 sampler_desc.mip_filter = mip_filters[selected_mip_filter];
805 sampler_desc.min_filter = min_filters[selected_min_filter];
806 auto sampler = context->GetSamplerLibrary()->GetSampler(sampler_desc);
807 FS::BindTex(cmd, boston, sampler);
808
809 pass->AddCommand(std::move(cmd));
810 }
811 pass->EncodeCommands();
812 }
813
814 if (!buffer->SubmitCommands()) {
815 return false;
816 }
817 return true;
818 };
819 OpenPlaygroundHere(callback);
820 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::kCount4, impeller::kLinear, impeller::kNearest, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::SamplerDescriptor::min_filter, impeller::SamplerDescriptor::mip_filter, impeller::Command::pipeline, and impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel().

## ◆ TEST_P() [355/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanLookupRenderTargetProperties |
| ) |  |

Definition at line 1283 of file renderer_unittests.cc.

1283 {
1284 auto context = GetContext();
1285 auto cmd_buffer = context->CreateCommandBuffer();
1286 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1287 GetContext()->GetResourceAllocator());
1288
1289 auto render_target =
1290 RenderTarget::CreateOffscreen(*context, *render_target_cache, {100, 100});
1291 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1292
1293 EXPECT_EQ(render_pass->GetSampleCount(), render_target.GetSampleCount());
1294 EXPECT_EQ(render_pass->GetRenderTargetPixelFormat(),
1295 render_target.GetRenderTargetPixelFormat());
1296 EXPECT_EQ(render_pass->HasStencilAttachment(),
1297 render_target.GetStencilAttachment().has_value());
1298 EXPECT_EQ(render_pass->GetRenderTargetSize(),
1299 render_target.GetRenderTargetSize());
1300 }

References impeller::RenderTarget::CreateOffscreen().

## ◆ TEST_P() [356/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanPreAllocateCommands |
| ) |  |

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 =
1275 RenderTarget::CreateOffscreen(*context, *render_target_cache, {100, 100});
1276 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1277
1278 render_pass->ReserveCommands(100u);
1279
1280 EXPECT_EQ(render_pass->GetCommands().capacity(), 100u);
1281 }

References impeller::RenderTarget::CreateOffscreen().

## ◆ TEST_P() [357/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderInstanced |
| ) |  |

Definition at line 386 of file renderer_unittests.cc.

386 {
387 if (GetParam() == PlaygroundBackend::kOpenGLES) {
388 GTEST_SKIP_("Instancing is not supported on OpenGL.");
389 }
390 using VS = InstancedDrawVertexShader;
391 using FS = InstancedDrawFragmentShader;
392
393 VertexBufferBuilder<VS::PerVertexData> builder;
394
395 ASSERT_EQ(Tessellator::Result::kSuccess,
396 Tessellator{}.Tessellate(
397 PathBuilder{}
398 .AddRect(Rect::MakeXYWH(10, 10, 100, 100))
399 .TakePath(FillType::kPositive),
400 1.0f,
401 [&builder](const float* vertices, size_t vertices_count,
402 const uint16_t* indices, size_t indices_count) {
403 for (auto i = 0u; i < vertices_count * 2; i += 2) {
404 VS::PerVertexData data;
405 data.vtx = {vertices[i], vertices[i + 1]};
406 builder.AppendVertex(data);
407 }
408 for (auto i = 0u; i < indices_count; i++) {
409 builder.AppendIndex(indices[i]);
410 }
411 return true;
412 }));
413
414 ASSERT_NE(GetContext(), nullptr);
415 auto pipeline =
416 GetContext()
417 ->GetPipelineLibrary()
418 ->GetPipeline(PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(
419 *GetContext())
420 ->SetSampleCount(SampleCount::kCount4)
421 .SetStencilAttachmentDescriptors(std::nullopt))
422
423 .Get();
424 ASSERT_TRUE(pipeline && pipeline->IsValid());
425
426 Command cmd;
427 cmd.pipeline = pipeline;
428 DEBUG_COMMAND_INFO(cmd, "InstancedDraw");
429
430 static constexpr size_t kInstancesCount = 5u;
431 VS::InstanceInfo<kInstancesCount> instances;
432 for (size_t i = 0; i < kInstancesCount; i++) {
433 instances.colors[i] = Color::Random();
434 }
435
436 ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool {
437 VS::FrameInfo frame_info;
438 EXPECT_EQ(pass.GetOrthographicTransform(),
439 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
440 frame_info.mvp =
441 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
442 VS::BindFrameInfo(cmd,
443 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
444 VS::BindInstanceInfo(
445 cmd, pass.GetTransientsBuffer().EmplaceStorageBuffer(instances));
446 cmd.BindVertices(builder.CreateVertexBuffer(pass.GetTransientsBuffer()));
447
448 cmd.instance_count = kInstancesCount;
449 pass.AddCommand(std::move(cmd));
450 return true;
451 }));
452 }

References impeller::RenderPass::AddCommand(), impeller::PathBuilder::AddRect(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendIndex(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendVertex(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::HostBuffer::EmplaceStorageBuffer(), impeller::HostBuffer::EmplaceUniform(), impeller::RenderPass::GetOrthographicTransform(), impeller::RenderPass::GetRenderTargetSize(), impeller::RenderPass::GetTransientsBuffer(), impeller::Command::instance_count, impeller::kCount4, impeller::kOpenGLES, impeller::kPositive, impeller::Tessellator::kSuccess, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Command::pipeline, impeller::Color::Random(), and impeller::Tessellator::Tessellate().

## ◆ TEST_P() [358/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderMultiplePrimitives |
| ) |  |

Definition at line 208 of file renderer_unittests.cc.

208 {
209 using VS = BoxFadeVertexShader;
210 using FS = BoxFadeFragmentShader;
211 auto context = GetContext();
212 ASSERT_TRUE(context);
213 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
214 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
215 ASSERT_TRUE(desc.has_value());
216 desc->SetSampleCount(SampleCount::kCount4);
217 desc->SetStencilAttachmentDescriptors(std::nullopt);
218 auto box_pipeline =
219 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
220 ASSERT_TRUE(box_pipeline);
221
222 // Vertex buffer.
223 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
224 vertex_builder.SetLabel("Box");
225 vertex_builder.AddVertices({
226 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
227 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
228 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
229 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
230 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
231 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
232 });
233 auto vertex_buffer =
234 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
235 ASSERT_TRUE(vertex_buffer);
236
237 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
238 auto boston = CreateTextureForFixture("boston.jpg");
239 ASSERT_TRUE(bridge && boston);
240 auto sampler = context->GetSamplerLibrary()->GetSampler({});
241 ASSERT_TRUE(sampler);
242
243 SinglePassCallback callback = [&](RenderPass& pass) {
244 Command cmd;
245 DEBUG_COMMAND_INFO(cmd, "Box");
246 cmd.pipeline = box_pipeline;
247
248 cmd.BindVertices(vertex_buffer);
249
250 FS::FrameInfo frame_info;
251 frame_info.current_time = GetSecondsElapsed();
252 frame_info.cursor_position = GetCursorPosition();
253 frame_info.window_size.x = GetWindowSize().width;
254 frame_info.window_size.y = GetWindowSize().height;
255
256 FS::BindFrameInfo(cmd,
257 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
258 FS::BindContents1(cmd, boston, sampler);
259 FS::BindContents2(cmd, bridge, sampler);
260
261 for (size_t i = 0; i < 1; i++) {
262 for (size_t j = 0; j < 1; j++) {
263 VS::UniformBuffer uniforms;
264 EXPECT_EQ(pass.GetOrthographicTransform(),
265 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
266 uniforms.mvp = pass.GetOrthographicTransform() *
267 Matrix::MakeScale(GetContentScale()) *
268 Matrix::MakeTranslation({i * 50.0f, j * 50.0f, 0.0f});
269 VS::BindUniformBuffer(
270 cmd, pass.GetTransientsBuffer().EmplaceUniform(uniforms));
271 if (!pass.AddCommand(std::move(cmd))) {
272 return false;
273 }
274 }
275 }
276
277 return true;
278 };
279 OpenPlaygroundHere(callback);
280 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::kCount4, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Command::pipeline, and impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel().

## ◆ TEST_P() [359/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderPerspectiveCube |
| ) |  |

Definition at line 117 of file renderer_unittests.cc.

117 {
118 using VS = ColorsVertexShader;
119 using FS = ColorsFragmentShader;
120 auto context = GetContext();
121 ASSERT_TRUE(context);
122 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
123 ASSERT_TRUE(desc.has_value());
124 desc->SetCullMode(CullMode::kBackFace);
125 desc->SetWindingOrder(WindingOrder::kCounterClockwise);
126 desc->SetSampleCount(SampleCount::kCount4);
127 desc->SetStencilAttachmentDescriptors(std::nullopt);
128 auto pipeline =
129 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
130 ASSERT_TRUE(pipeline);
131
132 struct Cube {
133 VS::PerVertexData vertices[8] = {
134 // -Z
135 {{-1, -1, -1}, Color::Red()},
136 {{1, -1, -1}, Color::Yellow()},
137 {{1, 1, -1}, Color::Green()},
138 {{-1, 1, -1}, Color::Blue()},
139 // +Z
140 {{-1, -1, 1}, Color::Green()},
141 {{1, -1, 1}, Color::Blue()},
142 {{1, 1, 1}, Color::Red()},
143 {{-1, 1, 1}, Color::Yellow()},
144 };
145 uint16_t indices[36] = {
146 1, 5, 2, 2, 5, 6, // +X
147 4, 0, 7, 7, 0, 3, // -X
148 4, 5, 0, 0, 5, 1, // +Y
149 3, 2, 7, 7, 2, 6, // -Y
150 5, 4, 6, 6, 4, 7, // +Z
151 0, 1, 3, 3, 1, 2, // -Z
152 };
153 } cube;
154
155 VertexBuffer vertex_buffer;
156 {
157 auto device_buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
158 reinterpret_cast<uint8_t*>(&cube), sizeof(cube));
159 vertex_buffer.vertex_buffer = {
160 .buffer = device_buffer,
161 .range = Range(offsetof(Cube, vertices), sizeof(Cube::vertices))};
162 vertex_buffer.index_buffer = {
163 .buffer = device_buffer,
164 .range = Range(offsetof(Cube, indices), sizeof(Cube::indices))};
165 vertex_buffer.vertex_count = 36;
166 vertex_buffer.index_type = IndexType::k16bit;
167 }
168
169 auto sampler = context->GetSamplerLibrary()->GetSampler({});
170 ASSERT_TRUE(sampler);
171
172 Vector3 euler_angles;
173 SinglePassCallback callback = [&](RenderPass& pass) {
174 static Degrees fov_y(60);
175 static Scalar distance = 10;
176
177 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
178 ImGui::SliderFloat("Field of view", &fov_y.degrees, 0, 180);
179 ImGui::SliderFloat("Camera distance", &distance, 0, 30);
180 ImGui::End();
181
182 Command cmd;
183 DEBUG_COMMAND_INFO(cmd, "Perspective Cube");
184 cmd.pipeline = pipeline;
185
186 cmd.BindVertices(vertex_buffer);
187
188 VS::UniformBuffer uniforms;
189 Scalar time = GetSecondsElapsed();
190 euler_angles = Vector3(0.19 * time, 0.7 * time, 0.43 * time);
191
192 uniforms.mvp =
193 Matrix::MakePerspective(fov_y, pass.GetRenderTargetSize(), 0, 10) *
194 Matrix::MakeTranslation({0, 0, distance}) *
195 Matrix::MakeRotationX(Radians(euler_angles.x)) *
196 Matrix::MakeRotationY(Radians(euler_angles.y)) *
197 Matrix::MakeRotationZ(Radians(euler_angles.z));
198 VS::BindUniformBuffer(cmd,
199 pass.GetTransientsBuffer().EmplaceUniform(uniforms));
200 if (!pass.AddCommand(std::move(cmd))) {
201 return false;
202 }
203 return true;
204 };
205 OpenPlaygroundHere(callback);
206 }

References impeller::Command::BindVertices(), impeller::Color::Blue(), impeller::BufferView::buffer, DEBUG_COMMAND_INFO, impeller::Degrees::degrees, 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::Command::pipeline, 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() [360/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderToTexture |
| ) |  |

Definition at line 282 of file renderer_unittests.cc.

282 {
283 using VS = BoxFadeVertexShader;
284 using FS = BoxFadeFragmentShader;
285 auto context = GetContext();
286 ASSERT_TRUE(context);
287 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
288 auto pipeline_desc =
289 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
290 pipeline_desc->SetSampleCount(SampleCount::kCount1);
291
292 ASSERT_TRUE(pipeline_desc.has_value());
293 auto box_pipeline =
294 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
295 ASSERT_TRUE(box_pipeline);
296
297 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
298 vertex_builder.SetLabel("Box");
299 vertex_builder.AddVertices({
300 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
301 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
302 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
303 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
304 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
305 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
306 });
307 auto vertex_buffer =
308 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
309 ASSERT_TRUE(vertex_buffer);
310
311 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
312 auto boston = CreateTextureForFixture("boston.jpg");
313 ASSERT_TRUE(bridge && boston);
314 auto sampler = context->GetSamplerLibrary()->GetSampler({});
315 ASSERT_TRUE(sampler);
316 std::shared_ptr<RenderPass> r2t_pass;
317 auto cmd_buffer = context->CreateCommandBuffer();
318 ASSERT_TRUE(cmd_buffer);
319 {
320 ColorAttachment color0;
321 color0.load_action = LoadAction::kClear;
322 color0.store_action = StoreAction::kStore;
323
324 TextureDescriptor texture_descriptor;
325 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u), nullptr);
326 texture_descriptor.format =
327 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
328 texture_descriptor.storage_mode = StorageMode::kHostVisible;
329 texture_descriptor.size = {400, 400};
330 texture_descriptor.mip_count = 1u;
331 texture_descriptor.usage =
332 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
333
334 color0.texture =
335 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
336
337 ASSERT_TRUE(color0.IsValid());
338
339 color0.texture->SetLabel("r2t_target");
340
341 StencilAttachment stencil0;
342 stencil0.load_action = LoadAction::kClear;
343 stencil0.store_action = StoreAction::kDontCare;
344 TextureDescriptor stencil_texture_desc;
345 stencil_texture_desc.storage_mode = StorageMode::kDeviceTransient;
346 stencil_texture_desc.size = texture_descriptor.size;
347 stencil_texture_desc.format = PixelFormat::kS8UInt;
348 stencil_texture_desc.usage =
349 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
350 stencil0.texture =
351 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
352
353 RenderTarget r2t_desc;
354 r2t_desc.SetColorAttachment(color0, 0u);
355 r2t_desc.SetStencilAttachment(stencil0);
356 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
357 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
358 }
359
360 Command cmd;
361 DEBUG_COMMAND_INFO(cmd, "Box");
362 cmd.pipeline = box_pipeline;
363
364 cmd.BindVertices(vertex_buffer);
365
366 FS::FrameInfo frame_info;
367 frame_info.current_time = GetSecondsElapsed();
368 frame_info.cursor_position = GetCursorPosition();
369 frame_info.window_size.x = GetWindowSize().width;
370 frame_info.window_size.y = GetWindowSize().height;
371
372 FS::BindFrameInfo(cmd,
373 r2t_pass->GetTransientsBuffer().EmplaceUniform(frame_info));
374 FS::BindContents1(cmd, boston, sampler);
375 FS::BindContents2(cmd, bridge, sampler);
376
377 VS::UniformBuffer uniforms;
378 uniforms.mvp = Matrix::MakeOrthographic(ISize{1024, 768}) *
379 Matrix::MakeTranslation({50.0f, 50.0f, 0.0f});
380 VS::BindUniformBuffer(
381 cmd, r2t_pass->GetTransientsBuffer().EmplaceUniform(uniforms));
382 ASSERT_TRUE(r2t_pass->AddCommand(std::move(cmd)));
383 ASSERT_TRUE(r2t_pass->EncodeCommands());
384 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, 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::Command::pipeline, 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() [361/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexBehavior |
| ) |  |

Definition at line 1036 of file renderer_unittests.cc.

1036 {
1037 using VS = BoxFadeVertexShader;
1038
1039 // Do not create any index buffer if no indices were provided.
1040 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1041 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::kNone);
1042 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::kNone.

## ◆ TEST_P() [362/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexSize |
| ) |  |

Definition at line 1026 of file renderer_unittests.cc.

1026 {
1027 using VS = BoxFadeVertexShader;
1028
1029 // Default to 16bit index buffer size, as this is a reasonable default and
1030 // supported on all backends without extensions.
1031 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1032 vertex_builder.AppendIndex(0u);
1033 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::k16bit);
1034 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendIndex(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::k16bit.

## ◆ TEST_P() [363/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | InactiveUniforms |
| ) |  |

Definition at line 942 of file renderer_unittests.cc.

942 {
943 using VS = InactiveUniformsVertexShader;
944 using FS = InactiveUniformsFragmentShader;
945
946 auto context = GetContext();
947 auto pipeline_descriptor =
948 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
949 ASSERT_TRUE(pipeline_descriptor.has_value());
950 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
951 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
952 auto pipeline =
953 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
954 ASSERT_TRUE(pipeline && pipeline->IsValid());
955
956 SinglePassCallback callback = [&](RenderPass& pass) {
957 auto size = pass.GetRenderTargetSize();
958
959 Command cmd;
960 cmd.pipeline = pipeline;
961 DEBUG_COMMAND_INFO(cmd, "Inactive Uniform");
962 VertexBufferBuilder<VS::PerVertexData> builder;
963 builder.AddVertices({{Point()},
964 {Point(0, size.height)},
965 {Point(size.width, 0)},
966 {Point(size.width, 0)},
967 {Point(0, size.height)},
968 {Point(size.width, size.height)}});
969 cmd.BindVertices(builder.CreateVertexBuffer(pass.GetTransientsBuffer()));
970
971 VS::FrameInfo frame_info;
972 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
973 frame_info.mvp =
974 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
975 VS::BindFrameInfo(cmd,
976 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
977
978 FS::FragInfo fs_uniform = {.unused_color = Color::Red(),
979 .color = Color::Green()};
980 FS::BindFragInfo(cmd,
981 pass.GetTransientsBuffer().EmplaceUniform(fs_uniform));
982
983 pass.AddCommand(std::move(cmd));
984 return true;
985 };
986 OpenPlaygroundHere(callback);
987 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::Color::Green(), impeller::kCount4, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::Command::pipeline, and impeller::Color::Red().

## ◆ TEST_P() [364/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | StencilMask |
| ) |  |

Definition at line 1114 of file renderer_unittests.cc.

1114 {
1115 using VS = BoxFadeVertexShader;
1116 using FS = BoxFadeFragmentShader;
1117 auto context = GetContext();
1118 ASSERT_TRUE(context);
1119 using BoxFadePipelineBuilder = PipelineBuilder<VS, FS>;
1120 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1121 ASSERT_TRUE(desc.has_value());
1122
1123 // Vertex buffer.
1124 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1125 vertex_builder.SetLabel("Box");
1126 vertex_builder.AddVertices({
1127 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1128 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1129 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1130 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1131 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1132 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1133 });
1134 auto vertex_buffer =
1135 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
1136 ASSERT_TRUE(vertex_buffer);
1137
1138 desc->SetSampleCount(SampleCount::kCount4);
1139 desc->SetStencilAttachmentDescriptors(std::nullopt);
1140
1141 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
1142 auto boston = CreateTextureForFixture("boston.jpg");
1143 ASSERT_TRUE(bridge && boston);
1144 auto sampler = context->GetSamplerLibrary()->GetSampler({});
1145 ASSERT_TRUE(sampler);
1146
1147 static bool mirror = false;
1148 static int stencil_reference_write = 0xFF;
1149 static int stencil_reference_read = 0x1;
1150 std::vector<uint8_t> stencil_contents;
1151 static int last_stencil_contents_reference_value = 0;
1152 static int current_front_compare =
1153 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1154 static int current_back_compare =
1155 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1156 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
1157 auto buffer = context->CreateCommandBuffer();
1158 if (!buffer) {
1159 return false;
1160 }
1161 buffer->SetLabel("Playground Command Buffer");
1162
1163 {
1164 // Configure the stencil attachment for the test.
1165 RenderTarget::AttachmentConfig stencil_config;
1166 stencil_config.load_action = LoadAction::kLoad;
1167 stencil_config.store_action = StoreAction::kDontCare;
1168 stencil_config.storage_mode = StorageMode::kHostVisible;
1169 auto render_target_allocator =
1170 RenderTargetAllocator(context->GetResourceAllocator());
1171 render_target.SetupStencilAttachment(*context, render_target_allocator,
1172 render_target.GetRenderTargetSize(),
1173 true, "stencil", stencil_config);
1174 // Fill the stencil buffer with an checkerboard pattern.
1175 const auto target_width = render_target.GetRenderTargetSize().width;
1176 const auto target_height = render_target.GetRenderTargetSize().height;
1177 const size_t target_size = target_width * target_height;
1178 if (stencil_contents.size() != target_size ||
1179 last_stencil_contents_reference_value != stencil_reference_write) {
1180 stencil_contents.resize(target_size);
1181 last_stencil_contents_reference_value = stencil_reference_write;
1182 for (int y = 0; y < target_height; y++) {
1183 for (int x = 0; x < target_width; x++) {
1184 const auto index = y * target_width + x;
1185 const auto kCheckSize = 64;
1186 const auto value =
1187 (((y / kCheckSize) + (x / kCheckSize)) % 2 == 0) *
1188 stencil_reference_write;
1189 stencil_contents[index] = value;
1190 }
1191 }
1192 }
1193 if (!render_target.GetStencilAttachment()->texture->SetContents(
1194 stencil_contents.data(), stencil_contents.size(), 0, false)) {
1195 VALIDATION_LOG << "Could not upload stencil contents to device memory";
1196 return false;
1197 }
1198 auto pass = buffer->CreateRenderPass(render_target);
1199 if (!pass) {
1200 return false;
1201 }
1202 pass->SetLabel("Stencil Buffer");
1203 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1204 ImGui::SliderInt("Stencil Write Value", &stencil_reference_write, 0,
1205 0xFF);
1206 ImGui::SliderInt("Stencil Compare Value", &stencil_reference_read, 0,
1207 0xFF);
1208 ImGui::Checkbox("Back face mode", &mirror);
1209 ImGui::ListBox("Front face compare function", &current_front_compare,
1210 CompareFunctionUI().labels(), CompareFunctionUI().size());
1211 ImGui::ListBox("Back face compare function", &current_back_compare,
1212 CompareFunctionUI().labels(), CompareFunctionUI().size());
1213 ImGui::End();
1214
1215 StencilAttachmentDescriptor front;
1216 front.stencil_compare =
1217 CompareFunctionUI().FunctionOf(current_front_compare);
1218 StencilAttachmentDescriptor back;
1219 back.stencil_compare =
1220 CompareFunctionUI().FunctionOf(current_back_compare);
1221 desc->SetStencilAttachmentDescriptors(front, back);
1222 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
1223
1224 assert(pipeline && pipeline->IsValid());
1225
1226 Command cmd;
1227 DEBUG_COMMAND_INFO(cmd, "Box");
1228 cmd.pipeline = pipeline;
1229 cmd.stencil_reference = stencil_reference_read;
1230
1231 cmd.BindVertices(vertex_buffer);
1232
1233 VS::UniformBuffer uniforms;
1234 EXPECT_EQ(pass->GetOrthographicTransform(),
1235 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
1236 uniforms.mvp = pass->GetOrthographicTransform() *
1237 Matrix::MakeScale(GetContentScale());
1238 if (mirror) {
1239 uniforms.mvp = Matrix::MakeScale(Vector2(-1, 1)) * uniforms.mvp;
1240 }
1241 VS::BindUniformBuffer(
1242 cmd, pass->GetTransientsBuffer().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(cmd,
1251 pass->GetTransientsBuffer().EmplaceUniform(frame_info));
1252 FS::BindContents1(cmd, boston, sampler);
1253 FS::BindContents2(cmd, bridge, sampler);
1254 if (!pass->AddCommand(std::move(cmd))) {
1255 return false;
1256 }
1257 pass->EncodeCommands();
1258 }
1259
1260 if (!buffer->SubmitCommands()) {
1261 return false;
1262 }
1263 return true;
1264 };
1265 OpenPlaygroundHere(callback);
1266 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), CompareFunctionUI(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, 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::Command::pipeline, impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel(), impeller::StencilAttachmentDescriptor::stencil_compare, impeller::Command::stencil_reference, impeller::RenderTarget::AttachmentConfig::storage_mode, impeller::RenderTarget::AttachmentConfig::store_action, and VALIDATION_LOG.

## ◆ TEST_P() [365/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | TheImpeller |
| ) |  |

Definition at line 822 of file renderer_unittests.cc.

822 {
823 using VS = ImpellerVertexShader;
824 using FS = ImpellerFragmentShader;
825
826 auto context = GetContext();
827 auto pipeline_descriptor =
828 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
829 ASSERT_TRUE(pipeline_descriptor.has_value());
830 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
831 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
832 auto pipeline =
833 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
834 ASSERT_TRUE(pipeline && pipeline->IsValid());
835
836 auto blue_noise = CreateTextureForFixture("blue_noise.png");
837 SamplerDescriptor noise_sampler_desc;
838 noise_sampler_desc.width_address_mode = SamplerAddressMode::kRepeat;
839 noise_sampler_desc.height_address_mode = SamplerAddressMode::kRepeat;
840 auto noise_sampler =
841 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
842
843 auto cube_map = CreateTextureCubeForFixture(
844 {"table_mountain_px.png", "table_mountain_nx.png",
845 "table_mountain_py.png", "table_mountain_ny.png",
846 "table_mountain_pz.png", "table_mountain_nz.png"});
847 auto cube_map_sampler = context->GetSamplerLibrary()->GetSampler({});
848
849 SinglePassCallback callback = [&](RenderPass& pass) {
850 auto size = pass.GetRenderTargetSize();
851
852 Command cmd;
853 cmd.pipeline = pipeline;
854 DEBUG_COMMAND_INFO(cmd, "Impeller SDF scene");
855 VertexBufferBuilder<VS::PerVertexData> builder;
856 builder.AddVertices({{Point()},
857 {Point(0, size.height)},
858 {Point(size.width, 0)},
859 {Point(size.width, 0)},
860 {Point(0, size.height)},
861 {Point(size.width, size.height)}});
862 cmd.BindVertices(builder.CreateVertexBuffer(pass.GetTransientsBuffer()));
863
864 VS::FrameInfo frame_info;
865 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
866 frame_info.mvp = pass.GetOrthographicTransform();
867 VS::BindFrameInfo(cmd,
868 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
869
870 FS::FragInfo fs_uniform;
871 fs_uniform.texture_size = Point(size);
872 fs_uniform.time = GetSecondsElapsed();
873 FS::BindFragInfo(cmd,
874 pass.GetTransientsBuffer().EmplaceUniform(fs_uniform));
875 FS::BindBlueNoise(cmd, blue_noise, noise_sampler);
876 FS::BindCubeMap(cmd, cube_map, cube_map_sampler);
877
878 pass.AddCommand(std::move(cmd));
879 return true;
880 };
881 OpenPlaygroundHere(callback);
882 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::SamplerDescriptor::height_address_mode, impeller::kCount4, impeller::kRepeat, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Command::pipeline, and impeller::SamplerDescriptor::width_address_mode.

## ◆ TEST_P() [366/384]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | VertexBufferBuilder |
| ) |  |

Definition at line 1044 of file renderer_unittests.cc.

1044 {
1045 // Does not create index buffer if one is provided.
1046 using VS = BoxFadeVertexShader;
1047 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1048 vertex_builder.SetLabel("Box");
1049 vertex_builder.AddVertices({
1050 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1051 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1052 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1053 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1054 });
1055 vertex_builder.AppendIndex(0);
1056 vertex_builder.AppendIndex(1);
1057 vertex_builder.AppendIndex(2);
1058 vertex_builder.AppendIndex(1);
1059 vertex_builder.AppendIndex(2);
1060 vertex_builder.AppendIndex(3);
1061
1062 ASSERT_EQ(vertex_builder.GetIndexCount(), 6u);
1063 ASSERT_EQ(vertex_builder.GetVertexCount(), 4u);
1064 }

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

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanCreatePipelineFromRuntimeStage |
| ) |  |

Definition at line 245 of file runtime_stage_unittests.cc.

245 {
246 if (!BackendSupportsFragmentProgram()) {
247 GTEST_SKIP_("This backend doesn't support runtime effects.");
248 }
249 auto stages = OpenAssetAsRuntimeStage("ink_sparkle.frag.iplr");
250 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
251
252 ASSERT_TRUE(stage);
253 ASSERT_NE(stage, nullptr);
254 ASSERT_TRUE(RegisterStage(*stage));
255 auto library = GetContext()->GetShaderLibrary();
256 using VS = SimpleVertexShader;
257 PipelineDescriptor desc;
258 desc.SetLabel("Runtime Stage InkSparkle");
259 desc.AddStageEntrypoint(
260 library->GetFunction(VS::kEntrypointName, ShaderStage::kVertex));
261 desc.AddStageEntrypoint(
262 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment));
263 auto vertex_descriptor = std::make_shared<VertexDescriptor>();
264 vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
265 VS::kInterleavedBufferLayout);
266
267 desc.SetVertexDescriptor(std::move(vertex_descriptor));
268 ColorAttachmentDescriptor color0;
269 color0.format = GetContext()->GetCapabilities()->GetDefaultColorFormat();
270 StencilAttachmentDescriptor stencil0;
271 stencil0.stencil_compare = CompareFunction::kEqual;
272 desc.SetColorAttachmentDescriptor(0u, color0);
273 desc.SetStencilAttachmentDescriptors(stencil0);
274 const auto stencil_fmt =
275 GetContext()->GetCapabilities()->GetDefaultStencilFormat();
276 desc.SetStencilPixelFormat(stencil_fmt);
277 auto pipeline = GetContext()->GetPipelineLibrary()->GetPipeline(desc).Get();
278 ASSERT_NE(pipeline, nullptr);
279 }

References impeller::PipelineDescriptor::AddStageEntrypoint(), impeller::ColorAttachmentDescriptor::format, impeller::kEqual, impeller::kFragment, 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() [368/384]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadUniforms |
| ) |  |

Definition at line 61 of file runtime_stage_unittests.cc.

61 {
62 if (!BackendSupportsFragmentProgram()) {
63 GTEST_SKIP_("This backend doesn't support runtime effects.");
64 }
65
66 const std::shared_ptr<fml::Mapping> fixture =
67 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
68 ASSERT_TRUE(fixture);
69 ASSERT_GT(fixture->GetSize(), 0u);
70 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
71 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
72
73 ASSERT_TRUE(stage->IsValid());
74 ASSERT_EQ(stage->GetUniforms().size(), 17u);
75 {
76 auto uni = stage->GetUniform("u_color");
77 ASSERT_NE(uni, nullptr);
78 ASSERT_EQ(uni->dimensions.rows, 4u);
79 ASSERT_EQ(uni->dimensions.cols, 1u);
80 ASSERT_EQ(uni->location, 0u);
81 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
82 }
83 {
84 auto uni = stage->GetUniform("u_alpha");
85 ASSERT_NE(uni, nullptr);
86 ASSERT_EQ(uni->dimensions.rows, 1u);
87 ASSERT_EQ(uni->dimensions.cols, 1u);
88 ASSERT_EQ(uni->location, 1u);
89 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
90 }
91 {
92 auto uni = stage->GetUniform("u_sparkle_color");
93 ASSERT_NE(uni, nullptr);
94 ASSERT_EQ(uni->dimensions.rows, 4u);
95 ASSERT_EQ(uni->dimensions.cols, 1u);
96 ASSERT_EQ(uni->location, 2u);
97 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
98 }
99 {
100 auto uni = stage->GetUniform("u_sparkle_alpha");
101 ASSERT_NE(uni, nullptr);
102 ASSERT_EQ(uni->dimensions.rows, 1u);
103 ASSERT_EQ(uni->dimensions.cols, 1u);
104 ASSERT_EQ(uni->location, 3u);
105 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
106 }
107 {
108 auto uni = stage->GetUniform("u_blur");
109 ASSERT_NE(uni, nullptr);
110 ASSERT_EQ(uni->dimensions.rows, 1u);
111 ASSERT_EQ(uni->dimensions.cols, 1u);
112 ASSERT_EQ(uni->location, 4u);
113 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
114 }
115 {
116 auto uni = stage->GetUniform("u_radius_scale");
117 ASSERT_NE(uni, nullptr);
118 ASSERT_EQ(uni->dimensions.rows, 1u);
119 ASSERT_EQ(uni->dimensions.cols, 1u);
120 ASSERT_EQ(uni->location, 6u);
121 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
122 }
123 {
124 auto uni = stage->GetUniform("u_max_radius");
125 ASSERT_NE(uni, nullptr);
126 ASSERT_EQ(uni->dimensions.rows, 1u);
127 ASSERT_EQ(uni->dimensions.cols, 1u);
128 ASSERT_EQ(uni->location, 7u);
129 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
130 }
131 {
132 auto uni = stage->GetUniform("u_resolution_scale");
133 ASSERT_NE(uni, nullptr);
134 ASSERT_EQ(uni->dimensions.rows, 2u);
135 ASSERT_EQ(uni->dimensions.cols, 1u);
136 ASSERT_EQ(uni->location, 8u);
137 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
138 }
139 {
140 auto uni = stage->GetUniform("u_noise_scale");
141 ASSERT_NE(uni, nullptr);
142 ASSERT_EQ(uni->dimensions.rows, 2u);
143 ASSERT_EQ(uni->dimensions.cols, 1u);
144 ASSERT_EQ(uni->location, 9u);
145 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
146 }
147 {
148 auto uni = stage->GetUniform("u_noise_phase");
149 ASSERT_NE(uni, nullptr);
150 ASSERT_EQ(uni->dimensions.rows, 1u);
151 ASSERT_EQ(uni->dimensions.cols, 1u);
152 ASSERT_EQ(uni->location, 10u);
153 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
154 }
155
156 {
157 auto uni = stage->GetUniform("u_circle1");
158 ASSERT_NE(uni, nullptr);
159 ASSERT_EQ(uni->dimensions.rows, 2u);
160 ASSERT_EQ(uni->dimensions.cols, 1u);
161 ASSERT_EQ(uni->location, 11u);
162 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
163 }
164 {
165 auto uni = stage->GetUniform("u_circle2");
166 ASSERT_NE(uni, nullptr);
167 ASSERT_EQ(uni->dimensions.rows, 2u);
168 ASSERT_EQ(uni->dimensions.cols, 1u);
169 ASSERT_EQ(uni->location, 12u);
170 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
171 }
172 {
173 auto uni = stage->GetUniform("u_circle3");
174 ASSERT_NE(uni, nullptr);
175 ASSERT_EQ(uni->dimensions.rows, 2u);
176 ASSERT_EQ(uni->dimensions.cols, 1u);
177 ASSERT_EQ(uni->location, 13u);
178 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
179 }
180 {
181 auto uni = stage->GetUniform("u_rotation1");
182 ASSERT_NE(uni, nullptr);
183 ASSERT_EQ(uni->dimensions.rows, 2u);
184 ASSERT_EQ(uni->dimensions.cols, 1u);
185 ASSERT_EQ(uni->location, 14u);
186 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
187 }
188 {
189 auto uni = stage->GetUniform("u_rotation2");
190 ASSERT_NE(uni, nullptr);
191 ASSERT_EQ(uni->dimensions.rows, 2u);
192 ASSERT_EQ(uni->dimensions.cols, 1u);
193 ASSERT_EQ(uni->location, 15u);
194 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
195 }
196 {
197 auto uni = stage->GetUniform("u_rotation3");
198 ASSERT_NE(uni, nullptr);
199 ASSERT_EQ(uni->dimensions.rows, 2u);
200 ASSERT_EQ(uni->dimensions.cols, 1u);
201 ASSERT_EQ(uni->location, 16u);
202 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
203 }
204 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kFloat, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [369/384]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadValidBlob |
| ) |  |

Definition at line 27 of file runtime_stage_unittests.cc.

27 {
28 if (!BackendSupportsFragmentProgram()) {
29 GTEST_SKIP_("This backend doesn't support runtime effects.");
30 }
31
32 const std::shared_ptr<fml::Mapping> fixture =
33 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
34 ASSERT_TRUE(fixture);
35 ASSERT_GT(fixture->GetSize(), 0u);
36 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
37 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
38 ASSERT_TRUE(stage->IsValid());
39 ASSERT_EQ(stage->GetShaderStage(), RuntimeShaderStage::kFragment);
40 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kFragment, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [370/384]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanRegisterStage |
| ) |  |

Definition at line 206 of file runtime_stage_unittests.cc.

206 {
207 if (!BackendSupportsFragmentProgram()) {
208 GTEST_SKIP_("This backend doesn't support runtime effects.");
209 }
210
211 const std::shared_ptr<fml::Mapping> fixture =
212 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
213 ASSERT_TRUE(fixture);
214 ASSERT_GT(fixture->GetSize(), 0u);
215 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
216 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
217 ASSERT_TRUE(stage->IsValid());
218 std::promise<bool> registration;
219 auto future = registration.get_future();
220 auto library = GetContext()->GetShaderLibrary();
221 library->RegisterFunction(
222 stage->GetEntrypoint(), //
223 ToShaderStage(stage->GetShaderStage()), //
224 stage->GetCodeMapping(), //
225 fml::MakeCopyable([reg = std::move(registration)](bool result) mutable {
226 reg.set_value(result);
227 }));
228 ASSERT_TRUE(future.get());
229 {
230 auto function =
231 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
232 ASSERT_NE(function, nullptr);
233 }
234
235 // Check if unregistering works.
236
237 library->UnregisterFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
238 {
239 auto function =
240 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
241 ASSERT_EQ(function, nullptr);
242 }
243 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kFragment, impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::ToShaderStage().

## ◆ TEST_P() [371/384]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanRejectInvalidBlob |
| ) |  |

Definition at line 42 of file runtime_stage_unittests.cc.

42 {
43 if (!BackendSupportsFragmentProgram()) {
44 GTEST_SKIP_("This backend doesn't support runtime effects.");
45 }
46
47 ScopedValidationDisable disable_validation;
48 const std::shared_ptr<fml::Mapping> fixture =
49 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
50 ASSERT_TRUE(fixture);
51 auto junk_allocation = std::make_shared<Allocation>();
52 ASSERT_TRUE(junk_allocation->Truncate(fixture->GetSize(), false));
53 // Not meant to be secure. Just reject obviously bad blobs using magic
54 // numbers.
55 ::memset(junk_allocation->GetBuffer(), 127, junk_allocation->GetLength());
56 auto stages = RuntimeStage::DecodeRuntimeStages(
57 CreateMappingFromAllocation(junk_allocation));
58 ASSERT_FALSE(stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())]);
59 }

References impeller::CreateMappingFromAllocation(), impeller::RuntimeStage::DecodeRuntimeStages(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [372/384]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | ContainsExpectedShaderTypes |
| ) |  |

Definition at line 281 of file runtime_stage_unittests.cc.

281 {
282 auto stages = OpenAssetAsRuntimeStage("ink_sparkle.frag.iplr");
283 // Right now, SkSL gets implicitly bundled regardless of what the build rule
284 // for this test requested. After
285 // https://github.com/flutter/flutter/issues/138919, this may require a build
286 // rule change or a new test.
287 EXPECT_TRUE(stages[RuntimeStageBackend::kSkSL]);
288
289 EXPECT_TRUE(stages[RuntimeStageBackend::kOpenGLES]);
290 EXPECT_TRUE(stages[RuntimeStageBackend::kMetal]);
291 // TODO(dnfield): Flip this when
292 // https://github.com/flutter/flutter/issues/122823 is fixed.
293 EXPECT_FALSE(stages[RuntimeStageBackend::kVulkan]);
294 }

References impeller::kMetal, impeller::kOpenGLES, impeller::kSkSL, and impeller::kVulkan.

## ◆ TEST_P() [373/384]

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

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

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() [376/384]

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() [377/384]

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() [378/384]

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() [379/384]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasTextureIsRecycledWhenContentsAreRecreated |
| ) |  |

Definition at line 341 of file typographer_unittests.cc.

341 {
342 auto context = TypographerContextSkia::Make();
343 auto atlas_context = context->CreateGlyphAtlasContext();
344 ASSERT_TRUE(context && context->IsValid());
345 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
346 auto blob = SkTextBlob::MakeFromString("ABCDEFGHIJKLMNOPQRSTUVQXYZ123456789",
347 sk_font);
348 ASSERT_TRUE(blob);
349 auto atlas = CreateGlyphAtlas(
350 *GetContext(), context.get(), GlyphAtlas::Type::kColorBitmap, 32.0f,
351 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
352 auto old_packer = atlas_context->GetRectPacker();
353
354 ASSERT_NE(atlas, nullptr);
355 ASSERT_NE(atlas->GetTexture(), nullptr);
356 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
357
358 auto* first_texture = atlas->GetTexture().get();
359
360 // Now create a new glyph atlas with a completely different textblob.
361 // everything should be different except for the underlying atlas texture.
362
363 auto blob2 = SkTextBlob::MakeFromString("abcdefghijklmnopqrstuvwxyz123456789",
364 sk_font);
365 auto next_atlas = CreateGlyphAtlas(
366 *GetContext(), context.get(), GlyphAtlas::Type::kColorBitmap, 32.0f,
367 atlas_context, *MakeTextFrameFromTextBlobSkia(blob2));
368 ASSERT_NE(atlas, next_atlas);
369 auto* second_texture = next_atlas->GetTexture().get();
370
371 auto new_packer = atlas_context->GetRectPacker();
372
373 ASSERT_EQ(second_texture, first_texture);
374 ASSERT_NE(old_packer, new_packer);
375 }

References CreateGlyphAtlas(), impeller::GlyphAtlas::kColorBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [380/384]

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 std::move(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() [381/384]

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() [382/384]

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 alpha 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() [383/384]

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() [384/384]

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 824 of file aiks_unittests.cc.

Referenced by TEST_P().

## ◆ LastSample

int64_t impeller::testing::LastSample = 0
| static

Definition at line 20 of file archivist_unittests.cc.

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:32
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
DEBUG_COMMAND_INFO
#define DEBUG_COMMAND_INFO(obj, arg)
Definition: command.h:28
impeller::kPreConcat
@ kPreConcat
Definition: canvas_recorder.h:28
impeller::kDrawImage
@ kDrawImage
Definition: canvas_recorder.h:40
impeller::testing::CompareFunctionUI
static const CompareFunctionUIData & CompareFunctionUI()
Definition: renderer_unittests.cc:1109
impeller::BlendModeToString
const char * BlendModeToString(BlendMode blend_mode)
Definition: color.cc:47
impeller::kClipPath
@ kClipPath
Definition: canvas_recorder.h:42
impeller::TextureUsageMask
uint64_t TextureUsageMask
Definition: formats.h:295
impeller::TPoint::y
Type y
Definition: point.h:26
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::TPoint::Ceil
constexpr TPoint Ceil() const
Definition: point.h:191
impeller::testing::CompareFunctionUIData::IndexOf
int IndexOf(CompareFunction func) const
Definition: renderer_unittests.cc:1092
impeller::testing::CanRenderSweepGradientWithDithering
static void CanRenderSweepGradientWithDithering(AiksTest *aiks_test, bool use_dithering)
Definition: aiks_gradient_unittests.cc:140
impeller::kConcat
@ kConcat
Definition: canvas_recorder.h:27
impeller::kDrawPicture
@ kDrawPicture
Definition: canvas_recorder.h:45
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::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:225
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:169
impeller::TPoint::Min
constexpr TPoint Min(const TPoint &p) const
Definition: point.h:181
impeller::ScaleSigma
Sigma ScaleSigma(Sigma sigma)
Definition: directional_gaussian_blur_filter_contents.cc:27
impeller::kRotate
@ kRotate
Definition: canvas_recorder.h:33
impeller::TPoint::Round
static constexpr TPoint Round(const TPoint< U > &other)
Definition: point.h:44
impeller::Vector2
Point Vector2
Definition: point.h:312
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:1000
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_PLAYGROUND_POINT
#define IMPELLER_PLAYGROUND_POINT(default_position, radius, color)
Definition: widgets.h:15
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:311
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:435
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
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:189
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:721
impeller::kPiOver2
constexpr float kPiOver2
Definition: constants.h:32
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:94
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:38
impeller::kPhi
constexpr float kPhi
Definition: constants.h:53
impeller::kColor
@ kColor
Definition: geometry.h:36
impeller::testing::toColor
flutter::DlColor toColor(const float *components)
Definition: dl_unittests.cc:41
impeller::kDrawTextFrame
@ kDrawTextFrame
Definition: canvas_recorder.h:46
impeller::testing::CreateColorVertices
std::shared_ptr< VerticesGeometry > CreateColorVertices(const std::vector< Point > &vertices, const std::vector< Color > &colors)
Definition: vertices_contents_unittests.cc:25
impeller::kScale2
@ kScale2
Definition: canvas_recorder.h:30
impeller::Point
TPoint< Scalar > Point
Definition: point.h:308
impeller::k2Pi
constexpr float k2Pi
Definition: constants.h:29
impeller::Quad
std::array< Point, 4 > Quad
Definition: point.h:313
impeller::testing::CompareFunctionUIData::FunctionOf
CompareFunction FunctionOf(int index) const
Definition: renderer_unittests.cc:1102
impeller::testing::RGBToYUV
static Vector3 RGBToYUV(Vector3 rgb, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:2033
impeller::MipFilter
MipFilter
Definition: formats.h:412
impeller::SPrintF
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
impeller::testing::GetBlendModeSelection
static BlendModeSelection GetBlendModeSelection()
Definition: aiks_unittests.cc:1007
impeller::IPoint32
TPoint< int32_t > IPoint32
Definition: point.h:310
impeller::ScalarToHalf
constexpr InternalHalf ScalarToHalf(Scalar f)
Convert a scalar to a half precision float.
Definition: half.h:31
impeller::kDrawRect
@ kDrawRect
Definition: canvas_recorder.h:36
impeller::TPoint::Max
constexpr TPoint Max(const TPoint &p) const
Definition: point.h:185
impeller::testing::CanRenderRadialGradientWithDithering
static void CanRenderRadialGradientWithDithering(AiksTest *aiks_test, bool use_dithering)
Definition: aiks_gradient_unittests.cc:113
impeller::kSkew
@ kSkew
Definition: canvas_recorder.h:32
impeller::kClipRRect
@ kClipRRect
Definition: canvas_recorder.h:44
impeller::MinMagFilter
MinMagFilter
Definition: formats.h:404
impeller::kDrawImageRect
@ kDrawImageRect
Definition: canvas_recorder.h:41
impeller::testing::CanRenderLinearGradientWithDithering
static void CanRenderLinearGradientWithDithering(AiksTest *aiks_test, bool use_dithering)
Definition: aiks_gradient_unittests.cc:85
impeller::testing::CreateTestYUVTextures
static std::vector< std::shared_ptr< Texture > > CreateTestYUVTextures(Context *context, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:2050
_BLEND_MODE_NAME_CHECK
#define _BLEND_MODE_NAME_CHECK(blend_mode)
Definition: geometry_unittests.cc:1447
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:488
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::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::kTransform
@ kTransform
Definition: canvas_recorder.h:26
impeller::kDrawAtlas
@ kDrawAtlas
Definition: canvas_recorder.h:48
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::testing::CreatePassWithRectPath
auto CreatePassWithRectPath(Rect rect, std::optional< Rect > bounds_hint, bool collapse=false)
Definition: entity_unittests.cc:105
impeller::IRect
TRect< int64_t > IRect
Definition: rect.h:489
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:67
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:684
FLT_FORWARD
#define FLT_FORWARD(mock, real, method)
Definition: aiks_unittests.cc:3601
impeller::LineTo
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:22
impeller::Join
Join
Definition: path.h:24
RectNear
inline ::testing::AssertionResult RectNear(impeller::Rect a, impeller::Rect b)
Definition: geometry_asserts.h:56
impeller::kDrawPoints
@ kDrawPoints
Definition: canvas_recorder.h:39
impeller::IPoint
TPoint< int64_t > IPoint
Definition: point.h:309
ASSERT_VECTOR3_NEAR
#define ASSERT_VECTOR3_NEAR(a, b)
Definition: geometry_asserts.h:161
impeller::testing::kFontFixture
static constexpr std::string_view kFontFixture
Definition: aiks_unittests.cc:824
impeller::ScalarNearlyEqual
constexpr bool ScalarNearlyEqual(Scalar x, Scalar y, Scalar tolerance=kEhCloseEnough)
Definition: scalar.h:30
impeller::YUVColorSpace
YUVColorSpace
Definition: color.h:55
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:195
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
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:47
impeller::TPoint::Normalize
constexpr TPoint Normalize() const
Definition: point.h:203
impeller::kDrawPath
@ kDrawPath
Definition: canvas_recorder.h:34
impeller::kDrawRRect
@ kDrawRRect
Definition: canvas_recorder.h:37
ASSERT_COLOR_BUFFER_NEAR
#define ASSERT_COLOR_BUFFER_NEAR(a, b)
Definition: geometry_asserts.h:165
IMPELLER_PLAYGROUND_LINE
#define IMPELLER_PLAYGROUND_LINE(default_position_a, default_position_b, radius, color_a, color_b)
Definition: widgets.h:56
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:43
impeller::Cap
Cap
Definition: path.h:18
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::kRestoreToCount
@ kRestoreToCount
Definition: canvas_recorder.h:24