Fix WebGL reveal timing and flip texture readiness

This commit is contained in:
2026-06-10 13:54:54 +02:00
parent e3d66686b9
commit 97eab216b7
7 changed files with 210 additions and 36 deletions
+59 -12
View File
@@ -119,6 +119,13 @@ class BookTextureRendererModule extends BaseModule {
const latestRenderedBlockId = Math.max(0, Number(event.detail?.latestRenderedBlockId || 0));
const visibility = event.detail?.visibility || 'current';
this.currentSpread = spread || { left: [], right: [] };
if (document.documentElement.dataset.webglPageFlipActive === 'true' && this.activeAnimations.size === 0) {
this.markPipelineTiming('spreadUpdate:skip-during-flip', {
spreadIndex,
visibility
});
return;
}
if (latestBlockId && Number(latestBlockId) > latestRenderedBlockId) {
this.markPendingReveal(latestBlockId);
const id = String(latestBlockId);
@@ -674,9 +681,16 @@ class BookTextureRendererModule extends BaseModule {
collectRevealRegionCandidates() {
const candidates = [];
const sourceSpreads = Array.isArray(this.pagination?.spreads) && this.pagination.spreads.length
? this.pagination.spreads
: [this.currentSpread || { index: 0, left: [], right: [] }];
const sourceSpreads = [];
if (this.currentSpread) sourceSpreads.push(this.currentSpread);
if (Array.isArray(this.pagination?.spreads)) {
this.pagination.spreads.forEach((spread) => {
if (!spread) return;
if (this.currentSpread && Number(spread.index) === Number(this.currentSpread.index)) return;
sourceSpreads.push(spread);
});
}
if (!sourceSpreads.length) sourceSpreads.push({ index: 0, left: [], right: [] });
sourceSpreads.forEach((spread) => {
['left', 'right'].forEach((side) => {
const spreadLines = Array.isArray(spread?.[side]) ? spread[side] : [];
@@ -707,17 +721,31 @@ class BookTextureRendererModule extends BaseModule {
const fixedRegions = sortedRegions.filter(region => region.fixedDurationMs > 0);
let fallbackDelay = 0;
const totalArea = textRegions.reduce((sum, region) => sum + Math.max(1, region.area), 0);
const wordTimings = Array.isArray(animation.wordTimings) ? animation.wordTimings : [];
const canUseLineWordSpans = wordTimings.length > 0
&& textRegions.every(region => Number.isFinite(Number(region.blockWordStart)) && Number(region.blockWordCount) > 0);
textRegions.forEach((region) => {
const duration = totalArea > 0
? Math.max(1, totalDuration * (Math.max(1, region.area) / totalArea))
: Math.max(1, totalDuration / Math.max(1, textRegions.length));
timedRegions.push({
...region,
timing: { delay: fallbackDelay, duration }
if (canUseLineWordSpans) {
textRegions.forEach((region) => {
const timing = this.getLineTimingFromWords(region, wordTimings);
timedRegions.push({
...region,
timing
});
fallbackDelay = Math.max(fallbackDelay, timing.delay + timing.duration);
});
fallbackDelay += duration;
});
} else {
textRegions.forEach((region) => {
const duration = totalArea > 0
? Math.max(1, totalDuration * (Math.max(1, region.area) / totalArea))
: Math.max(1, totalDuration / Math.max(1, textRegions.length));
timedRegions.push({
...region,
timing: { delay: fallbackDelay, duration }
});
fallbackDelay += duration;
});
}
fixedRegions.forEach((region) => {
timedRegions.push({
@@ -738,6 +766,23 @@ class BookTextureRendererModule extends BaseModule {
});
}
getLineTimingFromWords(region = {}, wordTimings = []) {
const start = Math.max(0, Math.floor(Number(region.blockWordStart || 0)));
const count = Math.max(1, Math.floor(Number(region.blockWordCount || 1)));
const first = wordTimings[Math.min(start, wordTimings.length - 1)] || { delay: 0, duration: 1 };
const lastIndex = Math.min(wordTimings.length - 1, start + count - 1);
const last = wordTimings[lastIndex] || first;
const delay = Math.max(0, Number(first.delay || 0));
const end = Math.max(
delay + 1,
Number(last.delay || 0) + Math.max(1, Number(last.duration || 1))
);
return {
delay,
duration: Math.max(1, end - delay)
};
}
createRevealRegionForLine(side, lineRecord = {}, spreadIndex = null) {
const blockId = String(lineRecord?.blockId ?? '');
if (!blockId || !this.revealPublishBlockIds.has(blockId)) return null;
@@ -770,6 +815,8 @@ class BookTextureRendererModule extends BaseModule {
spreadIndex: Math.max(0, Number((spreadIndex ?? Math.floor(Number(lineRecord.pageIndex || 0) / 2)) || 0)),
blockId,
lineIndex: Number(lineRecord.lineIndex ?? lineRecord.pageLine ?? 0),
blockWordStart: Number(lineRecord.blockWordStart ?? 0),
blockWordCount: Number(lineRecord.lineWordCount ?? 0),
fixedDurationMs,
area: rectWidth * rectHeight,
pixelRect: { x: left, y: top, right, bottom },