Last active
September 21, 2024 13:22
-
-
Save admannon/700168ec388e8cbfc7fe5f840f7473c4 to your computer and use it in GitHub Desktop.
Thai Text Support for RPG Maker MV & MZ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//============================================================================= | |
// ThaiTextSupport.js | |
// This code is licensed under the terms of the MIT license | |
//============================================================================= | |
/*: | |
* @plugindesc | |
* Fix font render that contain upper or/and lower glypts in message box. | |
* @author Admannon | |
* | |
* @help This plugin does not provide plugin commands. | |
*/ | |
(function () { | |
// Intl.Segmenter polyfill | |
const Segmenter = | |
Intl.Segmenter || | |
(() => { | |
if (!Intl.v8BreakIterator) { | |
throw new Error("unsupported segmenter"); | |
} | |
function _granularityToV8Type(granularity) { | |
switch (granularity) { | |
case "word": | |
case "sentence": | |
case "line": | |
return granularity; | |
default: | |
return "character"; | |
} | |
} | |
return class Segmenter { | |
constructor(locales, { granularity } = {}) { | |
this._v8Instance = Intl.v8BreakIterator(locales ? [locales] : undefined, { | |
type: _granularityToV8Type(granularity), | |
}); | |
} | |
segment(text) { | |
this._v8Instance.adoptText(text); | |
let instance = this._v8Instance; | |
let start = instance.first(); | |
return { | |
*[Symbol.iterator]() { | |
while (start !== -1) { | |
let next = instance.next(); | |
if (next === -1) break; | |
yield { | |
segment: text.slice(start, next), | |
index: text.current, | |
input: text, | |
}; | |
start = next; | |
} | |
}, | |
}; | |
} | |
}; | |
})(); | |
// Segmenter Object | |
const iterator = new Segmenter("th"); | |
function makeGraphemeProxy(text) { | |
const graphemes = [...iterator.segment(text)].map((graphemeObj) => graphemeObj.segment); | |
const handler = { | |
get({ value }, accessorName) { | |
const graphemeAccessor = graphemes[accessorName]; | |
if (typeof graphemeAccessor == "function") { | |
return (...arguments) => { | |
const result = graphemeAccessor.call(graphemes, ...arguments); | |
return Array.isArray(result) ? result.join("") : result; | |
}; | |
} | |
if (graphemeAccessor) { | |
return graphemeAccessor; | |
} | |
const accessor = value[accessorName]; | |
return typeof accessor == "function" ? accessor.bind(value) : accessor; | |
}, | |
}; | |
return new Proxy({ value: text }, handler); | |
} | |
const WindowBasePrototypeConvertEscapeCharacters = Window_Base.prototype.convertEscapeCharacters; | |
Window_Base.prototype.convertEscapeCharacters = function (text) { | |
text = WindowBasePrototypeConvertEscapeCharacters.call(this, text); | |
text = makeGraphemeProxy(text); | |
return text; | |
}; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment