SceneBuilderTests.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. using System;
  2. using System.Linq;
  3. using Avalonia.Controls;
  4. using Avalonia.Media;
  5. using Avalonia.Rendering.SceneGraph;
  6. using Avalonia.UnitTests;
  7. using Avalonia.VisualTree;
  8. using Xunit;
  9. using Avalonia.Layout;
  10. using Moq;
  11. using Avalonia.Platform;
  12. using System.Reactive.Subjects;
  13. using Avalonia.Data;
  14. using Avalonia.Utilities;
  15. using Avalonia.Media.Imaging;
  16. namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
  17. {
  18. public partial class SceneBuilderTests
  19. {
  20. [Fact]
  21. public void Should_Build_Initial_Scene()
  22. {
  23. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  24. {
  25. Border border;
  26. TextBlock textBlock;
  27. var tree = new TestRoot
  28. {
  29. Child = border = new Border
  30. {
  31. Width = 100,
  32. Height = 100,
  33. Background = Brushes.Red,
  34. Child = textBlock = new TextBlock
  35. {
  36. Text = "Hello World",
  37. }
  38. }
  39. };
  40. tree.Measure(Size.Infinity);
  41. tree.Arrange(new Rect(tree.DesiredSize));
  42. var result = new Scene(tree);
  43. var sceneBuilder = new SceneBuilder();
  44. sceneBuilder.UpdateAll(result);
  45. Assert.Same(tree, ((VisualNode)result.Root).LayerRoot);
  46. Assert.Equal(1, result.Root.Children.Count);
  47. var borderNode = (VisualNode)result.Root.Children[0];
  48. Assert.Same(borderNode, result.FindNode(border));
  49. Assert.Same(border, borderNode.Visual);
  50. Assert.Equal(1, borderNode.Children.Count);
  51. Assert.Equal(1, borderNode.DrawOperations.Count);
  52. var backgroundNode = (RectangleNode)borderNode.DrawOperations[0].Item;
  53. Assert.Equal(Brushes.Red, backgroundNode.Brush);
  54. var textBlockNode = borderNode.Children[0];
  55. Assert.Same(textBlockNode, result.FindNode(textBlock));
  56. Assert.Same(textBlock, textBlockNode.Visual);
  57. Assert.Equal(1, textBlockNode.DrawOperations.Count);
  58. var textNode = (TextNode)textBlockNode.DrawOperations[0].Item;
  59. Assert.NotNull(textNode.Text);
  60. }
  61. }
  62. [Fact]
  63. public void Should_Respect_Margin_For_ClipBounds()
  64. {
  65. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  66. {
  67. Canvas canvas;
  68. var tree = new TestRoot
  69. {
  70. Width = 200,
  71. Height = 300,
  72. Child = new Border
  73. {
  74. Margin = new Thickness(10, 20, 30, 40),
  75. Child = canvas = new Canvas
  76. {
  77. Background = Brushes.AliceBlue,
  78. }
  79. }
  80. };
  81. tree.Measure(Size.Infinity);
  82. tree.Arrange(new Rect(tree.DesiredSize));
  83. var result = new Scene(tree);
  84. var sceneBuilder = new SceneBuilder();
  85. sceneBuilder.UpdateAll(result);
  86. var canvasNode = result.FindNode(canvas);
  87. Assert.Equal(new Rect(10, 20, 160, 240), canvasNode.ClipBounds);
  88. // Initial ClipBounds are correct, make sure they're still correct after updating canvas.
  89. result = result.CloneScene();
  90. Assert.True(sceneBuilder.Update(result, canvas));
  91. canvasNode = result.FindNode(canvas);
  92. Assert.Equal(new Rect(10, 20, 160, 240), canvasNode.ClipBounds);
  93. }
  94. }
  95. [Fact]
  96. public void ClipBounds_Should_Be_Intersection_With_Parent_ClipBounds()
  97. {
  98. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  99. {
  100. Border border;
  101. var tree = new TestRoot
  102. {
  103. Width = 200,
  104. Height = 300,
  105. Child = new Canvas
  106. {
  107. ClipToBounds = true,
  108. Width = 100,
  109. Height = 100,
  110. HorizontalAlignment = HorizontalAlignment.Left,
  111. VerticalAlignment = VerticalAlignment.Top,
  112. Children =
  113. {
  114. (border = new Border
  115. {
  116. Background = Brushes.AliceBlue,
  117. Width = 100,
  118. Height = 100,
  119. [Canvas.LeftProperty] = 50,
  120. [Canvas.TopProperty] = 50,
  121. })
  122. }
  123. }
  124. };
  125. tree.Measure(Size.Infinity);
  126. tree.Arrange(new Rect(tree.DesiredSize));
  127. var scene = new Scene(tree);
  128. var sceneBuilder = new SceneBuilder();
  129. sceneBuilder.UpdateAll(scene);
  130. var borderNode = scene.FindNode(border);
  131. Assert.Equal(new Rect(50, 50, 50, 50), borderNode.ClipBounds);
  132. }
  133. }
  134. [Fact]
  135. public void Should_Update_Descendent_ClipBounds_When_Margin_Changed()
  136. {
  137. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  138. {
  139. Border border;
  140. Canvas canvas;
  141. var tree = new TestRoot
  142. {
  143. Width = 200,
  144. Height = 300,
  145. Child = canvas = new Canvas
  146. {
  147. ClipToBounds = true,
  148. Width = 100,
  149. Height = 100,
  150. HorizontalAlignment = HorizontalAlignment.Left,
  151. VerticalAlignment = VerticalAlignment.Top,
  152. Children =
  153. {
  154. (border = new Border
  155. {
  156. Background = Brushes.AliceBlue,
  157. Width = 100,
  158. Height = 100,
  159. [Canvas.LeftProperty] = 50,
  160. [Canvas.TopProperty] = 50,
  161. })
  162. }
  163. }
  164. };
  165. tree.Measure(Size.Infinity);
  166. tree.Arrange(new Rect(tree.DesiredSize));
  167. var scene = new Scene(tree);
  168. var sceneBuilder = new SceneBuilder();
  169. sceneBuilder.UpdateAll(scene);
  170. var borderNode = scene.FindNode(border);
  171. Assert.Equal(new Rect(50, 50, 50, 50), borderNode.ClipBounds);
  172. canvas.Width = canvas.Height = 125;
  173. canvas.Measure(Size.Infinity);
  174. canvas.Arrange(new Rect(tree.DesiredSize));
  175. // Initial ClipBounds are correct, make sure they're still correct after updating canvas.
  176. scene = scene.CloneScene();
  177. Assert.True(sceneBuilder.Update(scene, canvas));
  178. borderNode = scene.FindNode(border);
  179. Assert.Equal(new Rect(50, 50, 75, 75), borderNode.ClipBounds);
  180. }
  181. }
  182. [Fact]
  183. public void Should_Respect_ZIndex()
  184. {
  185. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  186. {
  187. Border front;
  188. Border back;
  189. var tree = new TestRoot
  190. {
  191. Child = new Panel
  192. {
  193. Children =
  194. {
  195. (front = new Border
  196. {
  197. ZIndex = 1,
  198. }),
  199. (back = new Border
  200. {
  201. ZIndex = 0,
  202. }),
  203. }
  204. }
  205. };
  206. var result = new Scene(tree);
  207. var sceneBuilder = new SceneBuilder();
  208. sceneBuilder.UpdateAll(result);
  209. var panelNode = result.FindNode(tree.Child);
  210. var expected = new IVisual[] { back, front };
  211. var actual = panelNode.Children.OfType<IVisualNode>().Select(x => x.Visual).ToArray();
  212. Assert.Equal(expected, actual);
  213. }
  214. }
  215. [Fact]
  216. public void ClipBounds_Should_Be_In_Global_Coordinates()
  217. {
  218. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  219. {
  220. Border target;
  221. var tree = new TestRoot
  222. {
  223. Child = new Decorator
  224. {
  225. Margin = new Thickness(24, 26),
  226. Child = target = new Border
  227. {
  228. Margin = new Thickness(26, 24),
  229. Width = 100,
  230. Height = 100,
  231. }
  232. }
  233. };
  234. tree.Measure(Size.Infinity);
  235. tree.Arrange(new Rect(tree.DesiredSize));
  236. var result = new Scene(tree);
  237. var sceneBuilder = new SceneBuilder();
  238. sceneBuilder.UpdateAll(result);
  239. var targetNode = result.FindNode(target);
  240. Assert.Equal(new Rect(50, 50, 100, 100), targetNode.ClipBounds);
  241. }
  242. }
  243. [Fact]
  244. public void Transform_For_Control_With_RenderTransform_Should_Be_Correct_After_Update()
  245. {
  246. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  247. {
  248. Border border;
  249. var tree = new TestRoot
  250. {
  251. Width = 400,
  252. Height = 200,
  253. Child = new Decorator
  254. {
  255. Width = 200,
  256. Height = 100,
  257. Child = border = new Border
  258. {
  259. Background = Brushes.Red,
  260. HorizontalAlignment = HorizontalAlignment.Right,
  261. Width = 100,
  262. RenderTransform = new ScaleTransform(0.5, 1),
  263. }
  264. }
  265. };
  266. tree.Measure(Size.Infinity);
  267. tree.Arrange(new Rect(tree.DesiredSize));
  268. var scene = new Scene(tree);
  269. var sceneBuilder = new SceneBuilder();
  270. sceneBuilder.UpdateAll(scene);
  271. var expectedTransform = Matrix.CreateScale(0.5, 1) * Matrix.CreateTranslation(225, 50);
  272. var borderNode = scene.FindNode(border);
  273. Assert.Equal(expectedTransform, borderNode.Transform);
  274. scene = scene.CloneScene();
  275. Assert.True(sceneBuilder.Update(scene, border));
  276. borderNode = scene.FindNode(border);
  277. Assert.Equal(expectedTransform, borderNode.Transform);
  278. }
  279. }
  280. [Fact]
  281. public void Should_Update_Border_Background_Node()
  282. {
  283. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  284. {
  285. Border border;
  286. TextBlock textBlock;
  287. var tree = new TestRoot
  288. {
  289. Child = border = new Border
  290. {
  291. Width = 100,
  292. Height = 100,
  293. Background = Brushes.Red,
  294. Child = textBlock = new TextBlock
  295. {
  296. Foreground = Brushes.Green,
  297. Text = "Hello World",
  298. }
  299. }
  300. };
  301. tree.Measure(Size.Infinity);
  302. tree.Arrange(new Rect(tree.DesiredSize));
  303. var initial = new Scene(tree);
  304. var sceneBuilder = new SceneBuilder();
  305. sceneBuilder.UpdateAll(initial);
  306. var initialBackgroundNode = initial.FindNode(border).Children[0];
  307. var initialTextNode = initial.FindNode(textBlock).DrawOperations[0];
  308. Assert.NotNull(initialBackgroundNode);
  309. Assert.NotNull(initialTextNode);
  310. border.Background = Brushes.Green;
  311. var result = initial.CloneScene();
  312. sceneBuilder.Update(result, border);
  313. var borderNode = (VisualNode)result.Root.Children[0];
  314. Assert.Same(border, borderNode.Visual);
  315. var backgroundNode = (RectangleNode)borderNode.DrawOperations[0].Item;
  316. Assert.NotSame(initialBackgroundNode, backgroundNode);
  317. Assert.Equal(Brushes.Green, backgroundNode.Brush);
  318. var textBlockNode = (VisualNode)borderNode.Children[0];
  319. Assert.Same(textBlock, textBlockNode.Visual);
  320. var textNode = (TextNode)textBlockNode.DrawOperations[0].Item;
  321. Assert.Same(initialTextNode.Item, textNode);
  322. }
  323. }
  324. [Fact]
  325. public void Should_Update_When_Control_Added()
  326. {
  327. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  328. {
  329. Border border;
  330. var tree = new TestRoot
  331. {
  332. Width = 100,
  333. Height = 100,
  334. Child = border = new Border
  335. {
  336. Background = Brushes.Red,
  337. }
  338. };
  339. Canvas canvas;
  340. var decorator = new Decorator
  341. {
  342. Child = canvas = new Canvas(),
  343. };
  344. tree.Measure(Size.Infinity);
  345. tree.Arrange(new Rect(tree.DesiredSize));
  346. var initial = new Scene(tree);
  347. var sceneBuilder = new SceneBuilder();
  348. sceneBuilder.UpdateAll(initial);
  349. border.Child = decorator;
  350. var result = initial.CloneScene();
  351. Assert.True(sceneBuilder.Update(result, decorator));
  352. // Updating canvas should result in no-op as it should have been updated along
  353. // with decorator as part of the add opeation.
  354. Assert.False(sceneBuilder.Update(result, canvas));
  355. var borderNode = (VisualNode)result.Root.Children[0];
  356. Assert.Equal(1, borderNode.Children.Count);
  357. Assert.Equal(1, borderNode.DrawOperations.Count);
  358. var decoratorNode = (VisualNode)borderNode.Children[0];
  359. Assert.Same(decorator, decoratorNode.Visual);
  360. Assert.Same(decoratorNode, result.FindNode(decorator));
  361. var canvasNode = (VisualNode)decoratorNode.Children[0];
  362. Assert.Same(canvas, canvasNode.Visual);
  363. Assert.Same(canvasNode, result.FindNode(canvas));
  364. }
  365. }
  366. [Fact]
  367. public void Should_Update_When_Control_Removed()
  368. {
  369. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  370. {
  371. Border border;
  372. Decorator decorator;
  373. Canvas canvas;
  374. var tree = new TestRoot
  375. {
  376. Width = 100,
  377. Height = 100,
  378. Child = border = new Border
  379. {
  380. Background = Brushes.Red,
  381. Child = decorator = new Decorator
  382. {
  383. Child = canvas = new Canvas
  384. {
  385. Background = Brushes.AliceBlue,
  386. }
  387. }
  388. }
  389. };
  390. tree.Measure(Size.Infinity);
  391. tree.Arrange(new Rect(tree.DesiredSize));
  392. var initial = new Scene(tree);
  393. var sceneBuilder = new SceneBuilder();
  394. sceneBuilder.UpdateAll(initial);
  395. border.Child = null;
  396. var result = initial.CloneScene();
  397. Assert.True(sceneBuilder.Update(result, decorator));
  398. Assert.False(sceneBuilder.Update(result, canvas));
  399. var borderNode = (VisualNode)result.Root.Children[0];
  400. Assert.Equal(0, borderNode.Children.Count);
  401. Assert.Equal(1, borderNode.DrawOperations.Count);
  402. Assert.Null(result.FindNode(decorator));
  403. Assert.Equal(new Rect(0, 0, 100, 100), result.Layers.Single().Dirty.Single());
  404. }
  405. }
  406. [Fact]
  407. public void Should_Update_When_Control_Made_Invisible()
  408. {
  409. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  410. {
  411. Decorator decorator;
  412. Border border;
  413. Canvas canvas;
  414. var tree = new TestRoot
  415. {
  416. Width = 100,
  417. Height = 100,
  418. Child = decorator = new Decorator
  419. {
  420. Child = border = new Border
  421. {
  422. Background = Brushes.Red,
  423. Child = canvas = new Canvas(),
  424. }
  425. }
  426. };
  427. tree.Measure(Size.Infinity);
  428. tree.Arrange(new Rect(tree.DesiredSize));
  429. var initial = new Scene(tree);
  430. var sceneBuilder = new SceneBuilder();
  431. sceneBuilder.UpdateAll(initial);
  432. border.IsVisible = false;
  433. var result = initial.CloneScene();
  434. Assert.True(sceneBuilder.Update(result, border));
  435. Assert.False(sceneBuilder.Update(result, canvas));
  436. var decoratorNode = (VisualNode)result.Root.Children[0];
  437. Assert.Equal(0, decoratorNode.Children.Count);
  438. Assert.Null(result.FindNode(border));
  439. Assert.Null(result.FindNode(canvas));
  440. Assert.Equal(new Rect(0, 0, 100, 100), result.Layers.Single().Dirty.Single());
  441. }
  442. }
  443. [Fact]
  444. public void Should_Update_Descendent_Tranform_When_Margin_Changed()
  445. {
  446. using (TestApplication())
  447. {
  448. Decorator decorator;
  449. Border border;
  450. Canvas canvas;
  451. var tree = new TestRoot
  452. {
  453. Width = 100,
  454. Height = 100,
  455. Child = decorator = new Decorator
  456. {
  457. Margin = new Thickness(0, 10, 0, 0),
  458. Child = border = new Border
  459. {
  460. Child = canvas = new Canvas(),
  461. }
  462. }
  463. };
  464. var layout = AvaloniaLocator.Current.GetService<ILayoutManager>();
  465. layout.ExecuteInitialLayoutPass(tree);
  466. var scene = new Scene(tree);
  467. var sceneBuilder = new SceneBuilder();
  468. sceneBuilder.UpdateAll(scene);
  469. var borderNode = scene.FindNode(border);
  470. var canvasNode = scene.FindNode(canvas);
  471. Assert.Equal(Matrix.CreateTranslation(0, 10), borderNode.Transform);
  472. Assert.Equal(Matrix.CreateTranslation(0, 10), canvasNode.Transform);
  473. decorator.Margin = new Thickness(0, 20, 0, 0);
  474. layout.ExecuteLayoutPass();
  475. scene = scene.CloneScene();
  476. sceneBuilder.Update(scene, decorator);
  477. borderNode = scene.FindNode(border);
  478. canvasNode = scene.FindNode(canvas);
  479. Assert.Equal(Matrix.CreateTranslation(0, 20), borderNode.Transform);
  480. Assert.Equal(Matrix.CreateTranslation(0, 20), canvasNode.Transform);
  481. }
  482. }
  483. [Fact]
  484. public void DirtyRects_Should_Contain_Old_And_New_Bounds_When_Margin_Changed()
  485. {
  486. using (TestApplication())
  487. {
  488. Decorator decorator;
  489. Border border;
  490. Canvas canvas;
  491. var tree = new TestRoot
  492. {
  493. Width = 100,
  494. Height = 100,
  495. Child = decorator = new Decorator
  496. {
  497. Margin = new Thickness(0, 10, 0, 0),
  498. Child = border = new Border
  499. {
  500. Background = Brushes.Red,
  501. Child = canvas = new Canvas(),
  502. }
  503. }
  504. };
  505. var layout = AvaloniaLocator.Current.GetService<ILayoutManager>();
  506. layout.ExecuteInitialLayoutPass(tree);
  507. var scene = new Scene(tree);
  508. var sceneBuilder = new SceneBuilder();
  509. sceneBuilder.UpdateAll(scene);
  510. var borderNode = scene.FindNode(border);
  511. var canvasNode = scene.FindNode(canvas);
  512. Assert.Equal(Matrix.CreateTranslation(0, 10), borderNode.Transform);
  513. Assert.Equal(Matrix.CreateTranslation(0, 10), canvasNode.Transform);
  514. decorator.Margin = new Thickness(0, 20, 0, 0);
  515. layout.ExecuteLayoutPass();
  516. scene = scene.CloneScene();
  517. sceneBuilder.Update(scene, decorator);
  518. var rects = scene.Layers.Single().Dirty.ToArray();
  519. Assert.Equal(new[] { new Rect(0, 10, 100, 90) }, rects);
  520. }
  521. }
  522. [Fact]
  523. public void Resizing_Scene_Should_Add_DirtyRects()
  524. {
  525. using (TestApplication())
  526. {
  527. Decorator decorator;
  528. Border border;
  529. Canvas canvas;
  530. var tree = new TestRoot
  531. {
  532. Child = decorator = new Decorator
  533. {
  534. Margin = new Thickness(0, 10, 0, 0),
  535. Child = border = new Border
  536. {
  537. Background = Brushes.Red,
  538. Child = canvas = new Canvas(),
  539. }
  540. }
  541. };
  542. var animation = new BehaviorSubject<double>(0.5);
  543. border.Bind(Border.OpacityProperty, animation, BindingPriority.Animation);
  544. var scene = new Scene(tree);
  545. var sceneBuilder = new SceneBuilder();
  546. sceneBuilder.UpdateAll(scene);
  547. Assert.Equal(new Size(100, 100), scene.Size);
  548. tree.ClientSize = new Size(110, 120);
  549. scene = scene.CloneScene();
  550. sceneBuilder.Update(scene, tree);
  551. Assert.Equal(new Size(110, 120), scene.Size);
  552. var expected = new[]
  553. {
  554. new Rect(100, 0, 10, 100),
  555. new Rect(0, 100, 110, 20),
  556. };
  557. Assert.Equal(expected, scene.Layers[tree].Dirty.ToArray());
  558. Assert.Equal(expected, scene.Layers[border].Dirty.ToArray());
  559. }
  560. }
  561. [Fact]
  562. public void Setting_Opacity_Should_Add_Descendent_Bounds_To_DirtyRects()
  563. {
  564. using (TestApplication())
  565. {
  566. Decorator decorator;
  567. Border border;
  568. var tree = new TestRoot
  569. {
  570. Child = decorator = new Decorator
  571. {
  572. Child = border = new Border
  573. {
  574. Background = Brushes.Red,
  575. Width = 100,
  576. Height = 100,
  577. }
  578. }
  579. };
  580. tree.Measure(Size.Infinity);
  581. tree.Arrange(new Rect(tree.DesiredSize));
  582. var scene = new Scene(tree);
  583. var sceneBuilder = new SceneBuilder();
  584. sceneBuilder.UpdateAll(scene);
  585. decorator.Opacity = 0.5;
  586. scene = scene.CloneScene();
  587. sceneBuilder.Update(scene, decorator);
  588. Assert.NotEmpty(scene.Layers.Single().Dirty);
  589. var dirty = scene.Layers.Single().Dirty.Single();
  590. Assert.Equal(new Rect(0, 0, 100, 100), dirty);
  591. }
  592. }
  593. [Fact]
  594. public void Should_Set_GeometryClip()
  595. {
  596. using (TestApplication())
  597. {
  598. var clip = StreamGeometry.Parse("M100,0 L0,100 100,100");
  599. Decorator decorator;
  600. var tree = new TestRoot
  601. {
  602. Child = decorator = new Decorator
  603. {
  604. Clip = clip,
  605. }
  606. };
  607. var scene = new Scene(tree);
  608. var sceneBuilder = new SceneBuilder();
  609. sceneBuilder.UpdateAll(scene);
  610. var decoratorNode = scene.FindNode(decorator);
  611. Assert.Same(clip.PlatformImpl, decoratorNode.GeometryClip);
  612. }
  613. }
  614. [Fact]
  615. public void Disposing_Scene_Releases_DrawOperation_References()
  616. {
  617. using (TestApplication())
  618. {
  619. var bitmap = RefCountable.Create(Mock.Of<IBitmapImpl>());
  620. Image img;
  621. var tree = new TestRoot
  622. {
  623. Child = img = new Image
  624. {
  625. Source = new Bitmap(bitmap)
  626. }
  627. };
  628. Assert.Equal(2, bitmap.RefCount);
  629. IRef<IDrawOperation> operation;
  630. using (var scene = new Scene(tree))
  631. {
  632. var sceneBuilder = new SceneBuilder();
  633. sceneBuilder.UpdateAll(scene);
  634. operation = scene.FindNode(img).DrawOperations[0];
  635. Assert.Equal(1, operation.RefCount);
  636. Assert.Equal(3, bitmap.RefCount);
  637. }
  638. Assert.Equal(0, operation.RefCount);
  639. Assert.Equal(2, bitmap.RefCount);
  640. }
  641. }
  642. [Fact]
  643. public void Replacing_Control_Releases_DrawOperation_Reference()
  644. {
  645. using (TestApplication())
  646. {
  647. var bitmap = RefCountable.Create(Mock.Of<IBitmapImpl>());
  648. Image img;
  649. var tree = new TestRoot
  650. {
  651. Child = img = new Image
  652. {
  653. Source = new Bitmap(bitmap)
  654. }
  655. };
  656. var scene = new Scene(tree);
  657. var sceneBuilder = new SceneBuilder();
  658. sceneBuilder.UpdateAll(scene);
  659. var operation = scene.FindNode(img).DrawOperations[0];
  660. tree.Child = new Decorator();
  661. using (var result = scene.CloneScene())
  662. {
  663. sceneBuilder.Update(result, img);
  664. scene.Dispose();
  665. Assert.Equal(0, operation.RefCount);
  666. Assert.Equal(2, bitmap.RefCount);
  667. }
  668. }
  669. }
  670. private IDisposable TestApplication()
  671. {
  672. return UnitTestApplication.Start(
  673. TestServices.MockPlatformRenderInterface.With(
  674. layoutManager: new LayoutManager()));
  675. }
  676. }
  677. }