Correct WebGL book page projection
This commit is contained in:
@@ -40,6 +40,7 @@ class BookTextureRendererModule extends BaseModule {
|
||||
'drawPageLines',
|
||||
'drawLine',
|
||||
'drawWord',
|
||||
'getPageContent',
|
||||
'buildLineSegments',
|
||||
'startRevealAnimation',
|
||||
'fastForwardAnimations',
|
||||
@@ -145,30 +146,35 @@ class BookTextureRendererModule extends BaseModule {
|
||||
ctx.textBaseline = 'alphabetic';
|
||||
if ('fontKerning' in ctx) ctx.fontKerning = 'normal';
|
||||
if ('fontVariantCaps' in ctx) ctx.fontVariantCaps = 'normal';
|
||||
lines.forEach(line => this.drawLine(ctx, line));
|
||||
lines.forEach(line => this.drawLine(ctx, line, side));
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
drawLine(ctx, lineRecord = {}) {
|
||||
drawLine(ctx, lineRecord = {}, side = 'left') {
|
||||
const metrics = this.metrics;
|
||||
const content = this.getPageContent(side);
|
||||
const fontPx = Math.max(1, Number(lineRecord.fontPx || 22));
|
||||
const lineHeightPx = Math.max(fontPx + 2, Number(lineRecord.lineHeightPx || metrics.typographyLineHeightPx || 30));
|
||||
const fontStyle = lineRecord.fontStyle === 'italic' ? 'italic ' : '';
|
||||
const line = lineRecord.line || {};
|
||||
const nodes = Array.isArray(line.nodes) ? line.nodes : [];
|
||||
const baseY = metrics.content.y + (Number(lineRecord.pageLine || 0) * lineHeightPx) + fontPx;
|
||||
const baseY = content.y + (Number(lineRecord.pageLine || 0) * lineHeightPx) + fontPx;
|
||||
const ratio = line.isFinal || line.align === 'center' ? 0 : Number(line.ratio || 0);
|
||||
const naturalWidth = nodes.reduce((sum, node) => {
|
||||
if (node.type === 'box' || node.type === 'glue') return sum + Number(node.width || 0);
|
||||
return sum;
|
||||
}, 0);
|
||||
const centerOffset = line.align === 'center'
|
||||
? Math.max(0, (metrics.content.width - naturalWidth) / 2)
|
||||
? Math.max(0, (content.width - naturalWidth) / 2)
|
||||
: Number(line.offset || 0);
|
||||
let x = metrics.content.x + centerOffset;
|
||||
let wordIndex = 0;
|
||||
let x = content.x + centerOffset;
|
||||
const smallCaps = Boolean(lineRecord.smallCaps || line.smallCaps);
|
||||
const previousVariantCaps = 'fontVariantCaps' in ctx ? ctx.fontVariantCaps : null;
|
||||
const previousLetterSpacing = 'letterSpacing' in ctx ? ctx.letterSpacing : null;
|
||||
|
||||
ctx.font = `${fontStyle}${lineRecord.smallCaps ? 'small-caps ' : ''}${fontPx}px ${metrics.typography.fontFamily}`;
|
||||
if ('fontVariantCaps' in ctx) ctx.fontVariantCaps = smallCaps ? 'all-small-caps' : 'normal';
|
||||
if ('letterSpacing' in ctx) ctx.letterSpacing = smallCaps ? `${fontPx * 0.012}px` : '0px';
|
||||
ctx.font = `${fontStyle}${smallCaps ? 'small-caps ' : ''}${fontPx}px ${metrics.typography.fontFamily}`;
|
||||
if (lineRecord.dropCapText) {
|
||||
ctx.save();
|
||||
const alpha = this.getWordAlpha(lineRecord, 0);
|
||||
@@ -176,20 +182,33 @@ class BookTextureRendererModule extends BaseModule {
|
||||
ctx.restore();
|
||||
} else {
|
||||
ctx.globalAlpha *= alpha;
|
||||
ctx.font = `${Math.round(lineHeightPx * 2.14)}px "EB Garamond Initials", ${metrics.typography.fontFamily}`;
|
||||
ctx.font = `${Math.round(fontPx * 2.68)}px "EB Garamond Initials", ${metrics.typography.fontFamily}`;
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.fillText(
|
||||
String(lineRecord.dropCapText),
|
||||
metrics.content.x,
|
||||
metrics.content.y + (Number(lineRecord.pageLine || 0) * lineHeightPx) - (lineHeightPx * 0.05)
|
||||
content.x,
|
||||
content.y + (Number(lineRecord.pageLine || 0) * lineHeightPx) + (fontPx * 0.25)
|
||||
);
|
||||
ctx.restore();
|
||||
}
|
||||
ctx.font = `${fontStyle}${lineRecord.smallCaps ? 'small-caps ' : ''}${fontPx}px ${metrics.typography.fontFamily}`;
|
||||
if ('fontVariantCaps' in ctx) ctx.fontVariantCaps = smallCaps ? 'all-small-caps' : 'normal';
|
||||
if ('letterSpacing' in ctx) ctx.letterSpacing = smallCaps ? `${fontPx * 0.012}px` : '0px';
|
||||
ctx.font = `${fontStyle}${smallCaps ? 'small-caps ' : ''}${fontPx}px ${metrics.typography.fontFamily}`;
|
||||
}
|
||||
this.buildLineSegments(ctx, nodes, line, ratio).forEach((segment) => {
|
||||
this.drawWord(ctx, segment.value, x + segment.x, baseY, lineRecord, segment.wordIndex);
|
||||
});
|
||||
if ('fontVariantCaps' in ctx) ctx.fontVariantCaps = previousVariantCaps || 'normal';
|
||||
if ('letterSpacing' in ctx) ctx.letterSpacing = previousLetterSpacing || '0px';
|
||||
}
|
||||
|
||||
getPageContent(side = 'left') {
|
||||
return this.metrics?.contentBySide?.[side] || this.metrics?.content || {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: this.metrics?.width || 1,
|
||||
height: this.metrics?.height || 1
|
||||
};
|
||||
}
|
||||
|
||||
buildLineSegments(ctx, nodes = [], line = {}, ratio = 0) {
|
||||
|
||||
Reference in New Issue
Block a user