File:  [Isaki's NoNo m68k/m88k emulator] / nono / wx / fontmanager.cpp
Revision 1.1.1.6 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:31 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, v026, v025, v024, v023, v022, v021, HEAD
nono 1.1.0

//
// nono
// Copyright (C) 2021 nono project
// Licensed under nono-license.txt
//

//
// フォント管理
//

#include "fontmanager.h"
#include "privatechar.h"
#include "wxtextpanel.h"
#include "builtinrom.h"
#include "kaname12.h"

// グローバル参照用
FontManager *gFontManager;

// コンストラクタ
FontManager::FontManager()
{
}

// デストラクタ
FontManager::~FontManager()
{
	gFontManager = NULL;
}

// フォントを変更(設定)
void
FontManager::SetFont(FontId fontid_)
{
	fontid = fontid_;

	// フォントデータを更新。
	// 6x12, 8x16, 12x24 半角は X68030 CGROM にあるのでそれを使う。
	const uint8 *base;
	switch (fontid) {
	 case FontId::_6x12:
		base = Builtin::CGROM6x12();
		break;
	 case FontId::_8x16:
		base = Builtin::CGROM8x16();
		break;
	 case FontId::_12x24:
		base = Builtin::CGROM12x24();
		break;
	 default:
		PANIC("fontid=%d", fontid);
	}

	font_width = fontinfo[fontid].GetWidth();
	font_height = fontinfo[fontid].GetHeight();

	// フォントの行ストライド[byte] を計算。
	font_stride = (font_width + 7) / 8;
	font_bytes = font_stride * font_height;

	// 半角文字領域 256 文字全部をキャッシュする。
	// ASCII は 0x7f までだが X680x0 の CGROM の 0x80, 0x81, 0x82 には
	// '\\', '~', '|' が収納されている。
	// 制御文字領域を外字として使う。

	ascii_glyph.resize(256 * font_bytes);

	// CGROM に収録されている文字のうち半角ひらがななど使わないものもあるが
	// 避けるのも手間なので気にせずデータを作っておく。
	for (int ch = 0; ch < 256; ch++) {
		int idx = ch * font_bytes;
		memcpy(&ascii_glyph[idx], base + idx, font_bytes);
	}

	// 外字を上書きで割り当てる
	for (int i = 0; private_chars[i].code != 0; i++) {
		const auto& pchar = private_chars[i];
		const char *ptr;

		switch (fontid) {
		 case FontId::_6x12:
			ptr = (const char *)pchar.data12;
			break;
		 case FontId::_8x16:
			ptr = (const char *)pchar.data16;
			break;
		 case FontId::_12x24:
			ptr = (const char *)pchar.data24;
			break;
		 default:
			PANIC("corrupted fontid=%d", (int)fontid);
		}

		int idx = pchar.code * font_bytes;
		memcpy(&ascii_glyph[idx], ptr, font_bytes);
	}
}

// ASCII のグリフを返す
const uint8 *
FontManager::AsciiGlyph(uint8 code) const
{
	// 変更可能なグリフ
	if (__predict_false(code == 0x5c)) {
		if (glyph_5c) {
			code = 0x80;
		}
	} else if (__predict_false(code == 0x7e)) {
		if (glyph_7e) {
			code = 0x81;
		}
	} else if (__predict_false(code == 0x7c)) {
		if (glyph_7c) {
			code = 0x82;
		}
	}

	return &ascii_glyph[code * font_bytes];
}

// 漢字のグリフを返す
const uint8 *
FontManager::KanjiGlyph(uint16 sjiscode) const
{
	// Shift_JIS を JIS というかコードポイントに変換
	uint sh = (sjiscode >> 8);
	uint sl = sjiscode & 0xff;
	uint jh;
	uint jl;
	if (sh < 0xa0) {
		jh = sh - 0x71;
	} else {
		jh = sh - 0xb1;
	}
	jh = jh * 2 + 1;
	jl = sl;
	if (sl > 0x7f) {
		jl--;
	}
	if (jl < 0x9e) {
		jl -= 0x1f;
	} else {
		jl -= 0x7d;
		jh++;
	}
	// ここで JIS。これを CGROM 格納コードポイントに変換。
	jh -= 0x21;
	jl -= 0x21;
	if (jh >= 15) {
		jh -= 7;
	}
	int code = jh * 94 + jl;

	// XXX 見付からなかったらゲタ文字にしたい
	if (code < 0) {
		code = 0x6b;
	}

	// フォント領域
	const uint8 *base;
	switch (fontid) {
	 case FontId::_6x12:
		// 12x12 は内蔵フォントデータ
		base = builtin_kanji12;
		break;
	 case FontId::_8x16:
		// 16x16 は X680x0 CGROM のを使う。
		base = Builtin::CGROM16x16();
		break;
	 case FontId::_12x24:
		// 24x24 は X680x0 CGROM のを使う。
		base = Builtin::CGROM24x24();
		break;
	 default:
		// ここより先に必ず半角のほうでエラーが出るはず
		PANIC("corrupted fontid=%d", (int)fontid);
	}

	int stride = ((font_width * 2) + 7) / 8;
	int bytes = stride * font_height;
	return base + code * bytes;
}

// フォント種別一覧
/*static*/ const std::array<wxSize, FontId::Max>
FontManager::fontinfo = {
	// 順序はヘッダの FontId_* 識別子の順と揃えること
	FONT_6x12,
	FONT_8x16,
	FONT_12x24,
};

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.