route-graphics 1.43.0 → 1.44.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,6 +28,7 @@ Options:
28
28
  --height <pixels> Override render height
29
29
  --state <index> State index when YAML contains multiple states
30
30
  --time <ms> Sample animations at a manual time
31
+ --layout-report <path> Write a JSON layout snapshot beside the PNG
31
32
  --background-color <value> 0xRRGGBB, #RRGGBB, or decimal
32
33
  --browser-executable <path> Use a system Chrome/Chromium executable
33
34
  --wait-for-render-complete Wait for renderComplete before capture
@@ -101,6 +102,13 @@ const parseCliArgs = (argv) => {
101
102
  index += 1;
102
103
  options.timeMS = parseIntegerOption("Animation time", argv[index]);
103
104
  break;
105
+ case "--layout-report":
106
+ index += 1;
107
+ if (!argv[index] || argv[index].startsWith("-")) {
108
+ throw new Error("Layout report requires an output path.");
109
+ }
110
+ options.layoutReportPath = argv[index];
111
+ break;
104
112
  case "--background-color":
105
113
  index += 1;
106
114
  options.backgroundColor = argv[index];
@@ -320,6 +328,7 @@ const capturePng = async ({
320
328
  waitForRenderComplete,
321
329
  timeoutMS,
322
330
  browserExecutablePath,
331
+ includeLayoutReport,
323
332
  }) => {
324
333
  const browser = await chromium.launch({
325
334
  headless: true,
@@ -344,7 +353,7 @@ const capturePng = async ({
344
353
  waitUntil: "domcontentloaded",
345
354
  });
346
355
 
347
- const base64 = await page.evaluate(
356
+ const capture = await page.evaluate(
348
357
  async ({ moduleUrl, renderPayload }) => {
349
358
  const nextFrame = async (count = 2) => {
350
359
  await new Promise((resolve) => {
@@ -448,7 +457,16 @@ const capturePng = async ({
448
457
 
449
458
  await nextFrame(2);
450
459
 
451
- return await app.extractBase64();
460
+ // Pixi copies the framebuffer synchronously, then encodes it
461
+ // asynchronously. Snapshot geometry before yielding to another frame.
462
+ const imagePromise = app.extractBase64();
463
+ const layoutReport = renderPayload.includeLayoutReport
464
+ ? app.getLayoutReport()
465
+ : null;
466
+ return {
467
+ base64: await imagePromise,
468
+ layoutReport,
469
+ };
452
470
  } finally {
453
471
  if (renderTimeoutId !== null) {
454
472
  window.clearTimeout(renderTimeoutId);
@@ -467,6 +485,7 @@ const capturePng = async ({
467
485
  timeMS: timeMS ?? null,
468
486
  waitForRenderComplete,
469
487
  timeoutMS,
488
+ includeLayoutReport,
470
489
  },
471
490
  },
472
491
  );
@@ -475,7 +494,7 @@ const capturePng = async ({
475
494
  throw new Error(pageErrors.join("\n"));
476
495
  }
477
496
 
478
- return base64;
497
+ return capture;
479
498
  } finally {
480
499
  await browser.close();
481
500
  }
@@ -525,6 +544,12 @@ const main = async () => {
525
544
 
526
545
  const inputPath = path.resolve(process.cwd(), cliOptions.inputPath);
527
546
  const outputPath = path.resolve(process.cwd(), cliOptions.outputPath);
547
+ const layoutReportPath = cliOptions.layoutReportPath
548
+ ? path.resolve(process.cwd(), cliOptions.layoutReportPath)
549
+ : null;
550
+ if (layoutReportPath === outputPath || layoutReportPath === inputPath) {
551
+ exitWithError("Layout report must not overwrite the input or PNG output.");
552
+ }
528
553
 
529
554
  await ensureBundleExists();
530
555
 
@@ -545,7 +570,7 @@ const main = async () => {
545
570
 
546
571
  try {
547
572
  const renderStartedAt = performance.now();
548
- const base64 = await capturePng({
573
+ const { base64, layoutReport } = await capturePng({
549
574
  origin: assetServer.origin,
550
575
  width: renderPayload.width,
551
576
  height: renderPayload.height,
@@ -556,11 +581,19 @@ const main = async () => {
556
581
  waitForRenderComplete: cliOptions.waitForRenderComplete,
557
582
  timeoutMS: cliOptions.timeoutMS,
558
583
  browserExecutablePath: cliOptions.browserExecutablePath,
584
+ includeLayoutReport: layoutReportPath !== null,
559
585
  });
560
586
  const renderDurationMS = performance.now() - renderStartedAt;
561
587
 
562
588
  const writeStartedAt = performance.now();
563
589
  await writePngOutput(outputPath, base64);
590
+ if (layoutReportPath !== null) {
591
+ await fsPromises.mkdir(path.dirname(layoutReportPath), { recursive: true });
592
+ await fsPromises.writeFile(
593
+ layoutReportPath,
594
+ `${JSON.stringify(layoutReport, null, 2)}\n`,
595
+ );
596
+ }
564
597
  const writeDurationMS = performance.now() - writeStartedAt;
565
598
  const totalDurationMS = performance.now() - startedAt;
566
599