(function() {
	let __fontDataList, __fontSmallList, __fontJPNList;
	const __bootReady = Scene_Boot.prototype.isReady;
	Scene_Boot.prototype.isReady = function() {
		if (__bootReady.call(this)){
			function parseFont(tmp, list){
				let j = 0;
				for (let i = 0; i < tmp.length; i += 4){
					if (tmp[i] == 255) { list[j] = 1; }
					j++;
				}
			}
			let chrWidth = 161;
			let tmp = ImageManager.reserveSystem('Font');
			tmp = tmp._context.getImageData(0,0,tmp.width,tmp.height).data;
			__fontDataList = new Uint8Array(tmp.length >> 2);
			parseFont(tmp, __fontDataList);

			tmp = ImageManager.reserveSystem('FontSmall');
			tmp = tmp._context.getImageData(0,0,tmp.width,tmp.height).data;
			__fontSmallList = new Uint8Array(tmp.length >> 2);
			parseFont(tmp, __fontSmallList);

			chrWidth = 321;
			tmp = ImageManager.reserveSystem('FontJPN');
			tmp = tmp._context.getImageData(0,0,tmp.width,tmp.height).data;
			__fontJPNList = new Uint8Array(tmp.length >> 2);
			parseFont(tmp, __fontJPNList);
			return true;
		}else{
			return false;
		}
	};

	Bitmap.prototype.isSmallMode = function(){
		return this.fontSize <= 10;
	}

	let renderRect;
	const renderCvs = document.createElement("canvas");
	renderCvs.setAttribute("style","font-smooth: never; -webkit-font-smoothing : none;");

	const renderCtx = renderCvs.getContext('2d', {
		alpha: false,
		antialias: false,
		depth: false,
	});
	function setBigCanvas(){
		renderCvs.width = renderCvs.height = 16;
		renderCtx.font = "12px GameFont";
		renderRect = [0,0,renderCvs.width, renderCvs.height];
	}
	function setSmallCanvas(){
		renderCvs.width = renderCvs.height = 8;
		renderCtx.font = "8px GameFont";
		renderRect = [0,0,renderCvs.width, renderCvs.height];
	}
	setBigCanvas();

	function parseJPNChar(chr,oy){
		if(!oy){ oy=12 };
		renderCtx.paintOpacity
		renderCtx.fillStyle = "#000";
		renderCtx.fillRect(...renderRect);
		renderCtx.fillStyle = "#fff";
		renderCtx.fillText(chr,0,oy,renderRect[2],renderRect[3]);
		const data = renderCtx.getImageData(...renderRect).data;
		const newList = new Uint8Array(data.length>>2);
		let n;
		for (let i = 0; i < data.length; i+=4){
			if (data[i] > 144) {
				n = i>>2;
				if (n >= 0){ newList[n] = 1; }
			}
		}
		return newList;
	};

	function parseJPNSmallChar(chr){
		setSmallCanvas();
		const newList = parseJPNChar(chr,6);
		setBigCanvas();
		return newList;
	};

	Bitmap.prototype.drawText = function(text, x, y, maxWidth, lineHeight, align) {
		if (text !== undefined) {
			var tx = x;
			var ty = y + lineHeight - (lineHeight - this.fontSize * 0.7) / 2;
			var context = this._context;
			var alpha = context.globalAlpha;
			maxWidth = maxWidth || 0xffffffff;
			text = String(text);
			if (align != "left"){
				let txtWid = 0;
				for (let i = 0; i < text.length; i++){
					txtWid += this.textWidth(text[i]); };
				if (align == "center"){
					tx += maxWidth - txtWid >> 1;
				}else if (align == "right"){
					tx += maxWidth - txtWid;
				}
			}
			context.save();
			context.font = this._makeFontNameText();
			context.textAlign = align;
			context.textBaseline = 'alphabetic';
			context.globalAlpha = alpha;
			this._drawTextBody2(text, tx, ty, maxWidth);
			context.restore();
			this._setDirty();
		}
	};

	Bitmap.prototype.textWidth = function(chr) {
		if (this.isSmallMode()){
			return 16;
		}else{
			switch(chr){
				case '.': case ',': case "'": case ":":
				case 'f': case 'i': case 'j': case 'l': case 't':
				case '(': case ')':
				case ' ':
					return 10;
				default:
					const idx = findCharIndex(chr);
					if (idx == -1 || is16pxChar(idx)){
						return 32;
					}else{
						return 16;
					}
			}
		}
	};

	function findCharIndex(chr){
		switch (chr){
			case 'A':return 0;	case 'B':return 1;	case 'C':return 2;
			case 'D':return 3;	case 'E':return 4;	case 'F':return 5;
			case 'G':return 6;	case 'H':return 7;	case 'I':return 8;
			case 'J':return 9;	case 'K':return 10;	case 'L':return 11;
			case 'M':return 12;	case 'N':return 13;	case 'P':return 14;
			case 'Q':return 15;	case 'R':return 16;	case 'S':return 17;
			case 'T':return 18;	case 'U':return 19;	case 'V':return 20;
			case 'W':return 21;	case 'X':return 22;	case 'Y':return 23;
			case 'Z':return 24;	case 'O':			case '0':return 25;
			case '1':return 26;	case '2':return 27;	case '3':return 28;
			case '4':return 29;	case '5':return 30;	case '6':return 31;
			case '7':return 32;	case '8':return 33;	case '9':return 34;
			case '!':return 35;	case '?':return 36;	
			case '+':return 37;	case '-':return 38;	case '*':return 39;
			case ':':return 40;	case '"':return 41;	case "'":return 42;
			case '→':return 43;	case '%':return 44;	case '.':return 45;
			case ',':return 46;	case '(':return 74;	case ')':return 75;
			case '/':return 76;	case '×':return 179;case '●':return 137;
			case 'Ä':return 77;	case 'Ö':return 78;	case 'Ü':return 79;

			case 'a':return 47;	case 'b':return 48;	case 'c':return 49;
			case 'd':return 50;	case 'e':return 51;	case 'f':return 52;
			case 'g':return 53;	case 'h':return 54;	case 'i':return 55;
			case 'j':return 56;	case 'k':return 57;	case 'l':return 58;
			case 'm':return 59;	case 'n':return 60;	case 'o':return 61;
			case 'p':return 62;	case 'q':return 63;	case 'r':return 64;
			case 's':return 65;	case 't':return 66;	case 'u':return 67;
			case 'v':return 68;	case 'w':return 69;	case 'x':return 70;
			case 'y':return 71;	case 'z':return 72;	case 'ß':return 73;
			case ' ':return -2; case '　':return -2;
case "あ":return 80;case "い":return 81;case "う":return 82;case "え":return 83;case "お":return 84;
case "か":return 85;case "き":return 86;case "く":return 87;case "け":return 88;case "こ":return 89;
case "さ":return 90;case "し":return 91;case "す":return 92;case "せ":return 93;case "そ":return 94;
case "た":return 95;case "ち":return 96;case "つ":return 97;case "て":return 98;case "と":return 99;
case "な":return 100;case "に":return 101;case "ぬ":return 102;case "ね":return 103;case "の":return 104;
case "は":return 105;case "ひ":return 106;case "ふ":return 107;case "へ":return 108;case "ほ":return 109;
case "ま":return 110;case "み":return 111;case "む":return 112;case "め":return 113;case "も":return 114;
case "や":return 115;case "ゆ":return 116;case "よ":return 117;case "ゔ":return 118;case "ヴ":return 119;
case "ら":return 120;case "り":return 121;case "る":return 122;case "れ":return 123;case "ろ":return 124;
case "わ":return 125;case "を":return 126;case "ん":return 127;
case "っ":return 128;case "ゃ":return 129;case "ゅ":return 130;case "ょ":return 131;
case "ぁ":return 132;case "ぃ":return 133;case "ぅ":return 134;case "ぇ":return 135;case "ぉ":return 136;
case "。":return 138;case "、":return 139;

case "ア":return 140;case "イ":return 141;case "ウ":return 142;case "エ":return 143;case "オ":return 144;
case "カ":return 145;case "キ":return 146;case "ク":return 147;case "ケ":return 148;case "コ":return 149;
case "サ":return 150;case "シ":return 151;case "ス":return 152;case "セ":return 153;case "ソ":return 154;
case "タ":return 155;case "チ":return 156;case "ツ":return 157;case "テ":return 158;case "ト":return 159;
case "ナ":return 160;case "ニ":return 161;case "ヌ":return 162;case "ネ":return 163;case "ノ":return 164;
case "ハ":return 165;case "ヒ":return 166;case "フ":return 167;case "ヘ":return 168;case "ホ":return 169;
case "マ":return 170;case "ミ":return 171;case "ム":return 172;case "メ":return 173;case "モ":return 174;
case "ヤ":return 175;case "ユ":return 176;case "ヨ":return 177;case "ー":return 178;
case "ラ":return 180;case "リ":return 181;case "ル":return 182;case "レ":return 183;case "ロ":return 184;
case "ワ":return 185;case "ヲ":return 186;case "ン":return 187;
case "ッ":return 188;case "ャ":return 189;case "ュ":return 190;case "ョ":return 191;
case "ァ":return 192;case "ィ":return 193;case "ゥ":return 194;case "ェ":return 195;case "ォ":return 196;

case "が":return 200;case "ぎ":return 201;case "ぐ":return 202;case "げ":return 203;case "ご":return 204;
case "ざ":return 205;case "じ":return 206;case "ず":return 207;case "ぜ":return 208;case "ぞ":return 209;
case "だ":return 210;case "ぢ":return 211;case "づ":return 212;case "で":return 213;case "ど":return 214;
case "ば":return 215;case "び":return 216;case "ぶ":return 217;case "べ":return 218;case "ぼ":return 219;

case "ガ":return 220;case "ギ":return 221;case "グ":return 222;case "ゲ":return 223;case "ゴ":return 224;
case "ザ":return 225;case "ジ":return 226;case "ズ":return 227;case "ゼ":return 228;case "ゾ":return 229;
case "ダ":return 230;case "ヂ":return 231;case "ヅ":return 232;case "デ":return 233;case "ド":return 234;
case "ぱ":return 235;case "ぴ":return 236;case "ぷ":return 237;case "ぺ":return 238;case "ぽ":return 239;

case "バ":return 240;case "ビ":return 241;case "ブ":return 242;case "ベ":return 243;case "ボ":return 244;
case "パ":return 245;case "ピ":return 246;case "プ":return 247;case "ペ":return 248;case "ポ":return 249;
default: return -1;
}
	}

	function is16pxChar(idx){
		return typeof idx == 'number' && idx >= 80;
	}

	Bitmap.prototype._drawTextBody2 = function(text, tx, ty, maxWidth) {
		tx = Math.floor(tx);
		ty = Math.floor(ty);
		let fontList, chrWidth, chrHeight, imgWidth;
		if (this.isSmallMode()){
			ty += 8;
			chrWidth = 8;
			chrHeight = 8;
			imgWidth = 160;
			fontList = __fontSmallList;
		}

		const context = this._context;
		context.fillStyle = this.textColor;

		let x,y,w,h,idx,chr,chrIdx;

		const chrRate = 2;
		for (let i = 0; i < text.length; i++){
			chr = text[i];
			chrIdx = findCharIndex(chr);
			if (!this.isSmallMode()){
				if(is16pxChar(chrIdx)){
					chrWidth = 16;
					chrHeight = 16;
					imgWidth = 320;
					fontList = __fontJPNList;
					chrIdx -= 80;
				}else{
					chrWidth = 8;
					chrHeight = 16;
					imgWidth = 160;
					fontList = __fontDataList;
				}
			}
			if (chrIdx == -2){
				tx += this.textWidth(chr);
			}else if (!fontList || chrIdx == -1){
				idx = 0;
				y = ty - 23;
				chrIdx = 
				(this.isSmallMode() ? parseJPNSmallChar : parseJPNChar)(chr);
				for (h = 0; h < chrHeight; h++){
					x = tx;
					for (w = 0; w < chrHeight; w++){
						if (chrIdx[idx++]){
							context.fillStyle = this.textColor;
							context.fillRect(x,y,chrRate,chrRate);
	
							context.fillStyle = "#000";
							x += chrRate;
							context.fillRect(x,y,chrRate,chrRate);
							context.fillRect(x,y+chrRate,chrRate,chrRate);
						}else{
							x += chrRate;
						}
					}
					y += chrRate;
				}
				context.fillStyle = this.textColor;
				tx += chrHeight*chrRate;
			}else{
				y = ty - 23;
				idx = (chrIdx % 20) * chrWidth + Math.floor(chrIdx / 20) * imgWidth * chrHeight;
				for (h = 0; h < chrHeight; h++){
					x = tx;
					for (w = 0; w < chrWidth; w++){
						if (fontList[idx++]){
							context.fillStyle = this.textColor;
							context.fillRect(x,y,chrRate,chrRate);
	
							context.fillStyle = "#000";
							x += chrRate;
							context.fillRect(x,y,chrRate,chrRate);
							context.fillRect(x,y+chrRate,chrRate,chrRate);
						}else{
							x += chrRate;
						}
					}
					context.fillStyle = this.textColor;
					idx += imgWidth-chrWidth;
					y += chrRate;
				}
				tx += this.textWidth(chr);
			}
		}
	};


	Window.prototype._updateCursor = function() {
		this._windowCursorSprite.alpha = 255;
		this._windowCursorSprite.visible = this.isOpen();
	};

	Window_Base.prototype.standardFontSize	= function() { return 24; };
	Window_Base.prototype.standardPadding	= function() { return 12; };
	Window_Base.prototype.textPadding		= function() { return 4; };
	Window_Base.prototype.standardBackOpacity	= function() { return 255; };
	Window_Base.prototype.textWidth = function(chr) { return this.contents.textWidth(chr); };

	Window_Message.prototype.windowWidth = function() {
		return Graphics.boxWidth + 12;
	};

	Window_Message.prototype.numVisibleRows = function() {
		return 3;
	};

	Window_Base.prototype.standardFontSize = function() {
		return 10;
	};
	Window_Message.prototype.standardFontSize = function() {
		return 24;
	};
	Window_ChoiceList.prototype.standardFontSize = function() {
		return 24;
	};
	Window_Help.prototype.standardFontSize = function() {
		return 24;
	};

	
})();
