aboutsummaryrefslogtreecommitdiffhomepage
path: root/public/bluebey-studio
diff options
context:
space:
mode:
Diffstat (limited to 'public/bluebey-studio')
-rw-r--r--public/bluebey-studio/src/caption.js31
1 files changed, 23 insertions, 8 deletions
diff --git a/public/bluebey-studio/src/caption.js b/public/bluebey-studio/src/caption.js
index df9c952..71759ea 100644
--- a/public/bluebey-studio/src/caption.js
+++ b/public/bluebey-studio/src/caption.js
@@ -101,21 +101,34 @@ const VERTICAL_OFFSETS = new Map();
for (const ch of SMALL_KANA) VERTICAL_OFFSETS.set(ch, { dx: 0.12, dy: -0.12 });
// 縦書きの句読点は、横書きの左下ではなく、字枠の右上に置く。
for (const ch of HANGING_PUNCTUATION) VERTICAL_OFFSETS.set(ch, { dx: 0.68, dy: -0.55 });
-for (const ch of '「『(〔') VERTICAL_OFFSETS.set(ch, { dx: 0.14, dy: -0.12 });
-for (const ch of '」』)〕') VERTICAL_OFFSETS.set(ch, { dx: -0.14, dy: 0.12 });
/**
* Characters drawn turned a quarter turn when stacked, so they read the way
- * 縦書き sets them: the prolonged sound mark `ー` becomes an upright bar.
+ * 縦書き sets them: the prolonged sound mark `ー` becomes an upright bar, and the
+ * brackets `「」『』[]()` turn so they open down the column.
*/
const VERTICAL_ROTATED = new Set(['ー', '~', '〜', '―']);
+const VERTICAL_BRACKETS = new Set([
+ '「', '」', '『', '』', '(', ')', '[', ']', '【', '】', '〔', '〕', '〈', '〉', '《', '》',
+]);
/**
* How far a rotated glyph is nudged down inside its cell, in em. The rotated `ー`
- * is centred otherwise, which leaves it hugging the character above it.
+ * is centred otherwise, which leaves it hugging the character above it; the
+ * brackets stay centred.
*/
const VERTICAL_ROTATED_DROP = 0.14;
+/**
+ * The downward nudge (em) for a glyph that is turned a quarter turn in 縦書き, or
+ * `null` when the glyph is drawn the ordinary way.
+ */
+function verticalRotation(ch) {
+ if (VERTICAL_ROTATED.has(ch)) return VERTICAL_ROTATED_DROP;
+ if (VERTICAL_BRACKETS.has(ch)) return 0;
+ return null;
+}
+
/** Offset used for the characters that need no special placement. */
const NO_OFFSET = Object.freeze({ dx: 0, dy: 0 });
@@ -426,9 +439,10 @@ function drawText(ctx, layout, state, font) {
const x = left + (lines.length - 1 - i) * step;
for (let j = 0; j < chars.length; j++) {
const ch = chars[j];
- if (VERTICAL_ROTATED.has(ch)) {
+ const drop = verticalRotation(ch);
+ if (drop !== null) {
ctx.save();
- ctx.translate(x + fontSize / 2, top + j * fontSize + fontSize / 2 + VERTICAL_ROTATED_DROP * fontSize);
+ ctx.translate(x + fontSize / 2, top + j * fontSize + fontSize / 2 + drop * fontSize);
ctx.rotate(Math.PI / 2);
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
@@ -492,9 +506,10 @@ function liveText(state, layout, font, fill, places) {
const x = left + (lines.length - 1 - i) * step;
for (let j = 0; j < chars.length; j++) {
const ch = chars[j];
- if (VERTICAL_ROTATED.has(ch)) {
+ const drop = verticalRotation(ch);
+ if (drop !== null) {
const cx = x + fontSize / 2;
- const cy = top + j * fontSize + fontSize / 2 + VERTICAL_ROTATED_DROP * fontSize;
+ const cy = top + j * fontSize + fontSize / 2 + drop * fontSize;
rotated.push(`<text ${base} text-anchor="middle" dy="0.36em"`
+ ` transform="rotate(90 ${formatNumber(cx, places)} ${formatNumber(cy, places)})"`
+ ` x="${formatNumber(cx, places)}" y="${formatNumber(cy, places)}">${escapeText(ch)}</text>`);