@@ -13566,5 +13566,80 @@ PAGX_TEST(PAGXTest, SMDataBindTypeMismatch) {
1356613566 EXPECT_EQ (smTimeline->getCurrentState (" main" ), " low" );
1356713567}
1356813568
13569+ // Smoke test: the demo pagx file (animation + viewmodel driving text channels) parses cleanly.
13570+ PAGX_TEST (PAGXTest, TextReshapeDemoParses) {
13571+ auto doc =
13572+ pagx::PAGXImporter::FromFile (ProjectPath::Absolute (" resources/text_reshape_demo.pagx" ));
13573+ ASSERT_NE (doc, nullptr );
13574+ for (const auto & err : doc->errors ) {
13575+ FAIL () << " parse error: " << err;
13576+ }
13577+ EXPECT_EQ (doc->layers .size (), 2u );
13578+ EXPECT_EQ (doc->animations .size (), 1u );
13579+ EXPECT_EQ (doc->dataBinds .size (), 2u );
13580+ ASSERT_NE (doc->viewModel , nullptr );
13581+ EXPECT_EQ (doc->viewModel ->id , " MainVM" );
13582+ EXPECT_NE (doc->findNode <pagx::Animation>(" textAnim" ), nullptr );
13583+ auto * vmText = doc->findNode <pagx::Text>(" vmText" );
13584+ ASSERT_NE (vmText, nullptr );
13585+ EXPECT_EQ (vmText->text , " VM Default" );
13586+ }
13587+
13588+ // Verifies the demo pagx's animation and viewmodel both reshape text through the runtime holder:
13589+ // after advancing the default timeline past the second keyframe, the animated Text's blob width
13590+ // changes to the "Animated" glyph extent; after driving the ViewModel's "title" property, the
13591+ // bound Text's blob width changes to the new content. Both go through PAGScene::draw so the
13592+ // holder's flush (setTextBlob) reflects in the bound tgfx::Text.
13593+ PAGX_TEST (PAGXTest, TextReshapeDemoAnimationAndViewModel) {
13594+ auto doc =
13595+ pagx::PAGXImporter::FromFile (ProjectPath::Absolute (" resources/text_reshape_demo.pagx" ));
13596+ ASSERT_NE (doc, nullptr );
13597+ pagx::FontConfig fontConfig;
13598+ for (const auto & fontPath : GetFallbackFontPaths ()) {
13599+ fontConfig.addFallbackFont (fontPath, 0 );
13600+ }
13601+ doc->applyLayout (&fontConfig);
13602+ auto scene = pagx::PAGScene::Make (doc);
13603+ ASSERT_NE (scene, nullptr );
13604+ auto surface = pagx::PAGSurface::MakeOffscreen (400 , 200 );
13605+ ASSERT_NE (surface, nullptr );
13606+
13607+ auto * animText = doc->findNode <pagx::Text>(" animText" );
13608+ ASSERT_NE (animText, nullptr );
13609+ auto * vmTextNode = doc->findNode <pagx::Text>(" vmText" );
13610+ ASSERT_NE (vmTextNode, nullptr );
13611+
13612+ // First frame: animation at time 0 ("Hello"), viewmodel default ("VM Default").
13613+ EXPECT_TRUE (scene->draw (surface));
13614+ auto binding = scene->mutableBinding ();
13615+ ASSERT_NE (binding, nullptr );
13616+ auto animRuntime = binding->get <tgfx::Text>(animText);
13617+ ASSERT_NE (animRuntime, nullptr );
13618+ ASSERT_NE (animRuntime->textBlob (), nullptr );
13619+ float animWidthBefore = animRuntime->textBlob ()->getBounds ().width ();
13620+ auto vmRuntime = binding->get <tgfx::Text>(vmTextNode);
13621+ ASSERT_NE (vmRuntime, nullptr );
13622+ ASSERT_NE (vmRuntime->textBlob (), nullptr );
13623+ float vmWidthBefore = vmRuntime->textBlob ()->getBounds ().width ();
13624+
13625+ // Advance the document-level animation past frame 60 (1s at 60fps) so the Hold keyframe value
13626+ // "Animated" takes effect, then draw.
13627+ auto defaultTimeline = scene->getDefaultTimeline ();
13628+ ASSERT_NE (defaultTimeline, nullptr );
13629+ defaultTimeline->advanceAndApply (1'000'000 );
13630+ EXPECT_TRUE (scene->draw (surface));
13631+ ASSERT_NE (animRuntime->textBlob (), nullptr );
13632+ float animWidthAfter = animRuntime->textBlob ()->getBounds ().width ();
13633+ // "Animated" is longer than "Hello", so the blob width must grow.
13634+ EXPECT_GT (animWidthAfter, animWidthBefore) << " animation did not reshape animText to 'Animated'" ;
13635+
13636+ // Drive the ViewModel's "title" property and draw: the bound vmText must reshape.
13637+ scene->viewModel ()->propertyString (" title" )->value (" ReshapedByVM" );
13638+ EXPECT_TRUE (scene->draw (surface));
13639+ ASSERT_NE (vmRuntime->textBlob (), nullptr );
13640+ float vmWidthAfter = vmRuntime->textBlob ()->getBounds ().width ();
13641+ EXPECT_NE (vmWidthAfter, vmWidthBefore) << " viewmodel did not reshape vmText to 'ReshapedByVM'" ;
13642+ }
13643+
1356913644// Canonical scene render test: Composition-wrapped layer with animation via scene.
1357013645} // namespace pag
0 commit comments