diff --git a/config/RSBE01_02/splits.txt b/config/RSBE01_02/splits.txt index afd89c83d..b22b87182 100644 --- a/config/RSBE01_02/splits.txt +++ b/config/RSBE01_02/splits.txt @@ -337,6 +337,23 @@ sora/st/st_data_container_multi.cpp: sora/st/st_data_container_magic.cpp: .sdata start:0x8059E860 end:0x8059E864 +nw4r/ut/ut_CharStrmReader.cpp: + .text start:0x8015C418 end:0x8015C528 + +nw4r/ut/ut_TagProcessorBase.cpp: + .text start:0x8015C528 end:0x8015CBF8 + .data start:0x80464580 end:0x804645A8 + .sdata2 start:0x805A2BB0 end:0x805A2BB8 + +nw4r/ut/ut_Font.cpp: + .text start:0x8015D8DC end:0x8015D984 + .data start:0x80464678 end:0x804646A8 + +nw4r/ut/ut_RomFont.cpp: + .text start:0x8015D984 end:0x8015DF8C + .data start:0x804646A8 end:0x80464768 + .sdata start:0x8059E868 end:0x8059E870 + Runtime.PPCEABI.H/__init_cpp_exceptions.cpp: .text start:0x803F1A08 end:0x803F1A78 .ctors start:0x804064E0 end:0x804064E4 rename:.ctors$10 diff --git a/config/RSBE01_02/symbols.txt b/config/RSBE01_02/symbols.txt index fedea1b01..a72572835 100644 --- a/config/RSBE01_02/symbols.txt +++ b/config/RSBE01_02/symbols.txt @@ -6534,18 +6534,18 @@ fn_8015C304 = .text:0x8015C304; // type:function size:0x44 Insert__Q44nw4r2ut6detail12LinkListImplFQ54nw4r2ut6detail12LinkListImpl8IteratorPQ34nw4r2ut12LinkListNode = .text:0x8015C348; // type:function size:0x2C Erase__Q44nw4r2ut6detail12LinkListImplFPQ34nw4r2ut12LinkListNode = .text:0x8015C374; // type:function size:0x30 fn_8015C3A4 = .text:0x8015C3A4; // type:function size:0x74 -fn_8015C418 = .text:0x8015C418; // type:function size:0x78 -fn_8015C490 = .text:0x8015C490; // type:function size:0x1C -fn_8015C4AC = .text:0x8015C4AC; // type:function size:0x1C -fn_8015C4C8 = .text:0x8015C4C8; // type:function size:0x60 -fn_8015C528 = .text:0x8015C528; // type:function size:0x10 -fn_8015C538 = .text:0x8015C538; // type:function size:0x40 -fn_8015C578 = .text:0x8015C578; // type:function size:0x130 -fn_8015C6A8 = .text:0x8015C6A8; // type:function size:0x1E8 -fn_8015C890 = .text:0x8015C890; // type:function size:0x10 -fn_8015C8A0 = .text:0x8015C8A0; // type:function size:0x40 -fn_8015C8E0 = .text:0x8015C8E0; // type:function size:0x130 -fn_8015CA10 = .text:0x8015CA10; // type:function size:0x1E8 +ReadNextCharUTF8__Q34nw4r2ut14CharStrmReaderFv = .text:0x8015C418; // type:function size:0x78 +ReadNextCharUTF16__Q34nw4r2ut14CharStrmReaderFv = .text:0x8015C490; // type:function size:0x1C +ReadNextCharCP1252__Q34nw4r2ut14CharStrmReaderFv = .text:0x8015C4AC; // type:function size:0x1C +ReadNextCharSJIS__Q34nw4r2ut14CharStrmReaderFv = .text:0x8015C4C8; // type:function size:0x60 +__ct__Q34nw4r2ut19TagProcessorBaseFv = .text:0x8015C528; // type:function size:0x10 +__dt__Q34nw4r2ut19TagProcessorBaseFv = .text:0x8015C538; // type:function size:0x40 +Process__Q34nw4r2ut19TagProcessorBaseFUsPQ34nw4r2ut15PrintContext = .text:0x8015C578; // type:function size:0x130 +CalcRect__Q34nw4r2ut19TagProcessorBaseFPQ34nw4r2ut4RectUsPQ34nw4r2ut15PrintContext = .text:0x8015C6A8; // type:function size:0x1E8 +__ct__Q34nw4r2ut19TagProcessorBaseFv = .text:0x8015C890; // type:function size:0x10 +__dt__Q34nw4r2ut19TagProcessorBaseFv = .text:0x8015C8A0; // type:function size:0x40 +Process__Q34nw4r2ut19TagProcessorBaseFUsPQ34nw4r2ut15PrintContext = .text:0x8015C8E0; // type:function size:0x130 +CalcRect__Q34nw4r2ut19TagProcessorBaseFPQ34nw4r2ut4RectUsPQ34nw4r2ut15PrintContext = .text:0x8015CA10; // type:function size:0x1E8 fn_8015CBF8 = .text:0x8015CBF8; // type:function size:0x8 fn_8015CC00 = .text:0x8015CC00; // type:function size:0x4 fn_8015CC04 = .text:0x8015CC04; // type:function size:0x8 @@ -6607,29 +6607,29 @@ fn_8015D8B8 = .text:0x8015D8B8; // type:function size:0x4 fn_8015D8BC = .text:0x8015D8BC; // type:function size:0x4 fn_8015D8C0 = .text:0x8015D8C0; // type:function size:0x4 fn_8015D8C4 = .text:0x8015D8C4; // type:function size:0x18 -fn_8015D8DC = .text:0x8015D8DC; // type:function size:0xA8 -fn_8015D984 = .text:0x8015D984; // type:function size:0x54 -fn_8015D9D8 = .text:0x8015D9D8; // type:function size:0x40 -fn_8015DA18 = .text:0x8015DA18; // type:function size:0x40 -fn_8015DA58 = .text:0x8015DA58; // type:function size:0xC -fn_8015DA64 = .text:0x8015DA64; // type:function size:0x5C -fn_8015DAC0 = .text:0x8015DAC0; // type:function size:0xC -fn_8015DACC = .text:0x8015DACC; // type:function size:0xC -fn_8015DAD8 = .text:0x8015DAD8; // type:function size:0xC -fn_8015DAE4 = .text:0x8015DAE4; // type:function size:0xC -fn_8015DAF0 = .text:0x8015DAF0; // type:function size:0xC -fn_8015DAFC = .text:0x8015DAFC; // type:function size:0xC -fn_8015DB08 = .text:0x8015DB08; // type:function size:0x8 -fn_8015DB10 = .text:0x8015DB10; // type:function size:0x8 -fn_8015DB18 = .text:0x8015DB18; // type:function size:0xC -fn_8015DB24 = .text:0x8015DB24; // type:function size:0x18 -fn_8015DB3C = .text:0x8015DB3C; // type:function size:0x1C -fn_8015DB58 = .text:0x8015DB58; // type:function size:0x100 -fn_8015DC58 = .text:0x8015DC58; // type:function size:0xC -fn_8015DC64 = .text:0x8015DC64; // type:function size:0x11C -fn_8015DD80 = .text:0x8015DD80; // type:function size:0x4C -fn_8015DDCC = .text:0x8015DDCC; // type:function size:0x18C -fn_8015DF58 = .text:0x8015DF58; // type:function size:0x34 +InitReaderFunc__Q34nw4r2ut4FontFQ34nw4r2ut12FontEncoding = .text:0x8015D8DC; // type:function size:0xA8 +__ct__Q34nw4r2ut7RomFontFv = .text:0x8015D984; // type:function size:0x54 +__dt__Q34nw4r2ut4FontFv = .text:0x8015D9D8; // type:function size:0x40 scope:weak +__dt__Q34nw4r2ut7RomFontFv = .text:0x8015DA18; // type:function size:0x40 +GetWidth__Q34nw4r2ut7RomFontCFv = .text:0x8015DA58; // type:function size:0xC +GetHeight__Q34nw4r2ut7RomFontCFv = .text:0x8015DA64; // type:function size:0x5C +GetAscent__Q34nw4r2ut7RomFontCFv = .text:0x8015DAC0; // type:function size:0xC +GetDescent__Q34nw4r2ut7RomFontCFv = .text:0x8015DACC; // type:function size:0xC +GetBaselinePos__Q34nw4r2ut7RomFontCFv = .text:0x8015DAD8; // type:function size:0xC +GetCellHeight__Q34nw4r2ut7RomFontCFv = .text:0x8015DAE4; // type:function size:0xC +GetCellWidth__Q34nw4r2ut7RomFontCFv = .text:0x8015DAF0; // type:function size:0xC +GetMaxCharWidth__Q34nw4r2ut7RomFontCFv = .text:0x8015DAFC; // type:function size:0xC +GetType__Q34nw4r2ut7RomFontCFv = .text:0x8015DB08; // type:function size:0x8 +GetTextureFormat__Q34nw4r2ut7RomFontCFv = .text:0x8015DB10; // type:function size:0x8 +GetLineFeed__Q34nw4r2ut7RomFontCFv = .text:0x8015DB18; // type:function size:0xC +GetDefaultCharWidths__Q34nw4r2ut7RomFontCFv = .text:0x8015DB24; // type:function size:0x18 +SetDefaultCharWidths__Q34nw4r2ut7RomFontFRCQ34nw4r2ut10CharWidths = .text:0x8015DB3C; // type:function size:0x1C +SetAlternateChar__Q34nw4r2ut7RomFontFUs = .text:0x8015DB58; // type:function size:0x100 +SetLineFeed__Q34nw4r2ut7RomFontFi = .text:0x8015DC58; // type:function size:0xC +GetCharWidth__Q34nw4r2ut7RomFontCFUs = .text:0x8015DC64; // type:function size:0x11C +GetCharWidths__Q34nw4r2ut7RomFontCFUs = .text:0x8015DD80; // type:function size:0x4C +GetGlyph__Q34nw4r2ut7RomFontCFPQ34nw4r2ut5GlyphUs = .text:0x8015DDCC; // type:function size:0x18C +GetEncoding__Q34nw4r2ut7RomFontCFv = .text:0x8015DF58; // type:function size:0x34 fn_8015DF8C = .text:0x8015DF8C; // type:function size:0x54 fn_8015DFE0 = .text:0x8015DFE0; // type:function size:0x40 fn_8015E020 = .text:0x8015E020; // type:function size:0xC @@ -6666,17 +6666,17 @@ fn_8015EB58 = .text:0x8015EB58; // type:function size:0x160 fn_8015ECB8 = .text:0x8015ECB8; // type:function size:0x40 fn_8015ECF8 = .text:0x8015ECF8; // type:function size:0xA58 fn_8015F750 = .text:0x8015F750; // type:function size:0xC4 -fn_8015F814 = .text:0x8015F814; // type:function size:0x60 -fn_8015F874 = .text:0x8015F874; // type:function size:0x60 +GetFontWidth__Q34nw4r2ut10CharWriterCFv = .text:0x8015F814; // type:function size:0x60 +GetFontHeight__Q34nw4r2ut10CharWriterCFv = .text:0x8015F874; // type:function size:0x60 fn_8015F8D4 = .text:0x8015F8D4; // type:function size:0x60 fn_8015F934 = .text:0x8015F934; // type:function size:0x130 fn_8015FA64 = .text:0x8015FA64; // type:function size:0x27C fn_8015FCE0 = .text:0x8015FCE0; // type:function size:0x150 fn_8015FE30 = .text:0x8015FE30; // type:function size:0x34C -fn_8016017C = .text:0x8016017C; // type:function size:0x7C +GetLineHeight__Q34nw4r2ut17TextWriterBaseCFv = .text:0x8016017C; // type:function size:0x7C fn_801601F8 = .text:0x801601F8; // type:function size:0x5C fn_80160254 = .text:0x80160254; // type:function size:0x58 -fn_801602AC = .text:0x801602AC; // type:function size:0x7C +GetLineHeight__Q34nw4r2ut17TextWriterBaseCFv = .text:0x801602AC; // type:function size:0x7C fn_80160328 = .text:0x80160328; // type:function size:0x288 fn_801605B0 = .text:0x801605B0; // type:function size:0x204 fn_801607B4 = .text:0x801607B4; // type:function size:0x688 @@ -8831,8 +8831,8 @@ fn_801DC698 = .text:0x801DC698; // type:function size:0x128 fn_801DC7C0 = .text:0x801DC7C0; // type:function size:0xFC fn_801DC8BC = .text:0x801DC8BC; // type:function size:0x1BC fn_801DCA78 = .text:0x801DCA78; // type:function size:0x290 -fn_801DCD08 = .text:0x801DCD08; // type:function size:0x150 -fn_801DCE58 = .text:0x801DCE58; // type:function size:0xB8 +OSGetFontTexture = .text:0x801DCD08; // type:function size:0x150 +OSGetFontWidth = .text:0x801DCE58; // type:function size:0xB8 OSDisableInterrupts = .text:0x801DCF10; // type:function size:0x14 scope:global fn_801DCF24 = .text:0x801DCF24; // type:function size:0x14 OSRestoreInterrupts = .text:0x801DCF38; // type:function size:0x24 scope:global @@ -26247,14 +26247,17 @@ __vt__20stDataMultiContainer = .data:0x80462C78; // type:object size:0x1C lbl_80462C94 = .data:0x80462C94; // type:object size:0x15 data:string lbl_80462CAC = .data:0x80462CAC; // type:object size:0x14 HomeBtnIcon = .data:0x80462CC0; // type:object size:0x18C0 scope:global align:32 -lbl_80464580 = .data:0x80464580; // type:object size:0x14 -lbl_80464594 = .data:0x80464594; // type:object size:0x14 +__vt__Q34nw4r2ut19TagProcessorBase = .data:0x80464580; // type:object size:0x14 +__vt__Q34nw4r2ut19TagProcessorBase = .data:0x80464594; // type:object size:0x14 lbl_804645A8 = .data:0x804645A8; // type:object size:0x68 lbl_80464610 = .data:0x80464610; // type:object size:0x68 -lbl_80464678 = .data:0x80464678; // type:object size:0x30 data:4byte -lbl_804646A8 = .data:0x804646A8; // type:object size:0x10 data:4byte -lbl_804646B8 = .data:0x804646B8; // type:object size:0x58 -lbl_80464710 = .data:0x80464710; // type:object size:0x58 +@639 = .data:0x80464678; // type:object size:0xC data:4byte scope:local +@640 = .data:0x80464684; // type:object size:0xC scope:local +@641 = .data:0x80464690; // type:object size:0xC scope:local +@642 = .data:0x8046469C; // type:object size:0xC scope:local +@1223 = .data:0x804646A8; // type:object size:0xC data:4byte scope:local +__vt__Q34nw4r2ut7RomFont = .data:0x804646B8; // type:object size:0x58 +__vt__Q34nw4r2ut4Font = .data:0x80464710; // type:object size:0x58 scope:weak lbl_80464768 = .data:0x80464768; // type:object size:0x10 data:4byte lbl_80464778 = .data:0x80464778; // type:object size:0x58 lbl_804647D0 = .data:0x804647D0; // type:object size:0x58 @@ -29648,7 +29651,7 @@ __RTTI__21stDataSimpleContainer = .sdata:0x8059E848; // type:object size:0x8 sco __RTTI__15stDataContainer = .sdata:0x8059E850; // type:object size:0x8 scope:weak __RTTI__20stDataMultiContainer = .sdata:0x8059E858; // type:object size:0x8 g_BlocMagicInit = .sdata:0x8059E860; // type:object size:0x4 data:4byte -lbl_8059E868 = .sdata:0x8059E868; // type:object size:0x8 data:2byte +mFontEncode__Q34nw4r2ut7RomFont = .sdata:0x8059E868; // type:object size:0x2 data:2byte lbl_8059E870 = .sdata:0x8059E870; // type:object size:0x4 data:4byte lbl_8059E874 = .sdata:0x8059E874; // type:object size:0xC data:byte lbl_8059E880 = .sdata:0x8059E880; // type:object size:0x20 @@ -32988,7 +32991,7 @@ lbl_805A2B9C = .sdata2:0x805A2B9C; // type:object size:0x4 align:4 data:float lbl_805A2BA0 = .sdata2:0x805A2BA0; // type:object size:0x4 align:4 data:float lbl_805A2BA4 = .sdata2:0x805A2BA4; // type:object size:0x4 align:4 data:float lbl_805A2BA8 = .sdata2:0x805A2BA8; // type:object size:0x4 align:4 data:float -lbl_805A2BB0 = .sdata2:0x805A2BB0; // type:object size:0x8 align:8 data:double +@2430 = .sdata2:0x805A2BB0; // type:object size:0x8 align:8 data:double scope:local lbl_805A2BB8 = .sdata2:0x805A2BB8; // type:object size:0x4 align:4 data:float lbl_805A2BBC = .sdata2:0x805A2BBC; // type:object size:0x4 align:4 data:float lbl_805A2BC0 = .sdata2:0x805A2BC0; // type:object size:0x8 align:8 data:double diff --git a/configure.py b/configure.py index d44984a5b..2a49b07b9 100755 --- a/configure.py +++ b/configure.py @@ -361,6 +361,10 @@ def MatchingFor(*versions): Object(Matching, "sora/st/st_data_container.cpp"), Object(Matching, "sora/st/st_data_container_multi.cpp"), Object(Matching, "sora/st/st_data_container_magic.cpp"), + Object(Matching, "nw4r/ut/ut_CharStrmReader.cpp", extra_cflags=["-RTTI off"]), + Object(Matching, "nw4r/ut/ut_TagProcessorBase.cpp", extra_cflags=["-RTTI off"]), + Object(Matching, "nw4r/ut/ut_Font.cpp", extra_cflags=["-RTTI off"]), + Object(Matching, "nw4r/ut/ut_RomFont.cpp", extra_cflags=["-RTTI off"]), ], }, # Common REL units diff --git a/src/nw4r/ut/ut_CharStrmReader.cpp b/src/nw4r/ut/ut_CharStrmReader.cpp new file mode 100644 index 000000000..2f1fc968b --- /dev/null +++ b/src/nw4r/ut/ut_CharStrmReader.cpp @@ -0,0 +1,49 @@ +#include + +namespace nw4r { +namespace ut { + +u16 CharStrmReader::ReadNextCharUTF8() { + u16 ch = GetChar(0); + if ((ch & 0x80) == 0) { + StepStrm(1); + } else if ((ch & 0xE0) == 0xC0) { + ch = ((ch & 0x1F) << 6) | (GetChar(1) & 0x3F); + StepStrm(2); + } else { + u8 second = GetChar(1); + u8 third = GetChar(2); + ch = ((ch & 0x1F) << 12) | ((second & 0x3F) << 6) | (third & 0x3F); + StepStrm(3); + } + return ch; +} + +u16 CharStrmReader::ReadNextCharUTF16() { + u16 ch = GetChar(0); + StepStrm(1); + return ch; +} + +u16 CharStrmReader::ReadNextCharCP1252() { + u16 ch = GetChar(0); + StepStrm(1); + return ch; +} + +u16 CharStrmReader::ReadNextCharSJIS() { + u16 ch; + u8 first = GetChar(0); + bool twoBytes = (first >= 0x81 && first < 0xA0) || first >= 0xE0; + if (twoBytes) { + ch = (first << 8) | GetChar(1); + StepStrm(2); + } else { + ch = first; + StepStrm(1); + } + return ch; +} + +} // namespace ut +} // namespace nw4r diff --git a/src/nw4r/ut/ut_Font.cpp b/src/nw4r/ut/ut_Font.cpp new file mode 100644 index 000000000..156504de5 --- /dev/null +++ b/src/nw4r/ut/ut_Font.cpp @@ -0,0 +1,25 @@ +#include + +namespace nw4r { +namespace ut { + +void Font::InitReaderFunc(FontEncoding encode) { + switch (encode) { + case FONT_ENCODING_UTF8: + mReadFunc = &CharStrmReader::ReadNextCharUTF8; + break; + case FONT_ENCODING_UTF16: + mReadFunc = &CharStrmReader::ReadNextCharUTF16; + break; + case FONT_ENCODING_SJIS: + mReadFunc = &CharStrmReader::ReadNextCharSJIS; + break; + case FONT_ENCODING_CP1252: + default: + mReadFunc = &CharStrmReader::ReadNextCharCP1252; + break; + } +} + +} // namespace ut +} // namespace nw4r diff --git a/src/nw4r/ut/ut_RomFont.cpp b/src/nw4r/ut/ut_RomFont.cpp new file mode 100644 index 000000000..0e76b53a6 --- /dev/null +++ b/src/nw4r/ut/ut_RomFont.cpp @@ -0,0 +1,174 @@ +#include + +namespace nw4r { +namespace ut { + +u16 RomFont::mFontEncode = 0xFFFF; + +RomFont::RomFont() : mFontHeader(nullptr), mAlternateChar('?') { + mDefaultWidths.left = 0; + mDefaultWidths.glyphWidth = 0; + mDefaultWidths.charWidth = 0; +} + +RomFont::~RomFont() { } + +int RomFont::GetWidth() const { + return mFontHeader->width; +} + +int RomFont::GetHeight() const { + return GetAscent() + GetDescent(); +} + +int RomFont::GetAscent() const { + return mFontHeader->ascent; +} + +int RomFont::GetDescent() const { + return mFontHeader->descent; +} + +int RomFont::GetBaselinePos() const { + return mFontHeader->ascent; +} + +int RomFont::GetCellHeight() const { + return mFontHeader->cellHeight; +} + +int RomFont::GetCellWidth() const { + return mFontHeader->cellWidth; +} + +int RomFont::GetMaxCharWidth() const { + return mFontHeader->width; +} + +Font::Type RomFont::GetType() const { + return TYPE_ROM; +} + +GXTexFmt RomFont::GetTextureFormat() const { + return GX_TF_I4; +} + +int RomFont::GetLineFeed() const { + return mFontHeader->leading; +} + +CharWidths RomFont::GetDefaultCharWidths() const { + return mDefaultWidths; +} + +void RomFont::SetDefaultCharWidths(const CharWidths& rWidths) { + mDefaultWidths = rWidths; +} + +namespace detail { + +inline bool IsSjisSingleByte(u16 ch) { // Name unknown + if (ch > 0xFF) { + return false; + } + return (ch >= 0x20 && ch <= 0x7E) || (ch >= 0xA1 && ch <= 0xDF); +} + +inline bool IsSjisDoubleByte(u16 ch) { // Name unknown + u8 trail = ch; + u8 lead = ch >> 8; + return lead >= 0x81 && lead <= 0x98 && trail >= 0x40 && trail <= 0xFC; +} + +} // namespace detail + +inline u16 RomFont::HandleUndefinedChar(u16 ch) const { + // Requires ANSI or SJIS ROM font encoding. + bool valid; + switch (mFontEncode) { + case OS_FONT_ENCODE_ANSI: + valid = ch >= 0x20 && ch <= 0xFF; + break; + case OS_FONT_ENCODE_SJIS: + valid = detail::IsSjisSingleByte(ch) || detail::IsSjisDoubleByte(ch); + break; + } + return valid ? ch : mAlternateChar; +} + +bool RomFont::SetAlternateChar(u16 ch) { + const u16 old = mAlternateChar; + mAlternateChar = 0xFFFF; + const u16 alternate = HandleUndefinedChar(ch); + if (alternate != 0xFFFF) { + mAlternateChar = ch; + return true; + } + mAlternateChar = old; + return false; +} + +void RomFont::SetLineFeed(int lf) { + mFontHeader->leading = lf; +} + +inline void RomFont::MakeCharPtr(char* pBuffer, u16 ch) const { + u8 high = ch >> 8; + if (high == 0) { + pBuffer[0] = ch; + pBuffer[1] = 0; + } else { + pBuffer[0] = high; + pBuffer[1] = ch; + pBuffer[2] = 0; + } +} + +int RomFont::GetCharWidth(u16 ch) const { + u32 width; + char buffer[CHAR_PTR_BUFFER_SIZE]; + MakeCharPtr(buffer, HandleUndefinedChar(ch)); + OSGetFontWidth(buffer, &width); + return width; +} + +CharWidths RomFont::GetCharWidths(u16 ch) const { + int width = GetCharWidth(ch); + CharWidths widths; + widths.left = 0; + widths.glyphWidth = width; + widths.charWidth = width; + return widths; +} + +void RomFont::GetGlyph(Glyph* pGlyph, u16 ch) const { + void* texture; + u32 x, y, width; + char buffer[CHAR_PTR_BUFFER_SIZE]; + MakeCharPtr(buffer, HandleUndefinedChar(ch)); + OSGetFontTexture(buffer, &texture, &x, &y, &width); + pGlyph->pTexture = texture; + pGlyph->widths.left = 0; + pGlyph->widths.glyphWidth = width; + pGlyph->widths.charWidth = width; + pGlyph->height = mFontHeader->cellHeight; + pGlyph->texFormat = GX_TF_I4; + pGlyph->texWidth = mFontHeader->sheetWidth; + pGlyph->texHeight = mFontHeader->sheetHeight; + pGlyph->cellX = x; + pGlyph->cellY = y; +} + +FontEncoding RomFont::GetEncoding() const { + switch (mFontEncode) { + case OS_FONT_ENCODE_ANSI: + return FONT_ENCODING_CP1252; + case OS_FONT_ENCODE_SJIS: + return FONT_ENCODING_SJIS; + default: + return FONT_ENCODING_CP1252; + } +} + +} // namespace ut +} // namespace nw4r diff --git a/src/nw4r/ut/ut_TagProcessorBase.cpp b/src/nw4r/ut/ut_TagProcessorBase.cpp new file mode 100644 index 000000000..7edb770c1 --- /dev/null +++ b/src/nw4r/ut/ut_TagProcessorBase.cpp @@ -0,0 +1,82 @@ +#include +#include + +#include + +namespace nw4r { +namespace ut { + +template +TagProcessorBase::TagProcessorBase() { } + +template +TagProcessorBase::~TagProcessorBase() { } + +template +void TagProcessorBase::ProcessLinefeed(ContextType* pCtx) { + TextWriterBase* writer = pCtx->writer; + f32 x = pCtx->x; + f32 y = writer->GetCursorY() + writer->GetLineHeight(); + writer->SetCursor(x, y); +} + +template +void TagProcessorBase::ProcessTab(ContextType* pCtx) { + TextWriterBase* writer = pCtx->writer; + int tabWidth = writer->GetTabWidth(); + if (tabWidth > 0) { + f32 charWidth = writer->IsWidthFixed() ? writer->GetFixedWidth() : writer->GetFontWidth(); + f32 offset = writer->GetCursorX() - pCtx->x; + f32 tabSize = tabWidth * charWidth; + int tab = static_cast(offset / tabSize) + 1; + writer->SetCursorX(pCtx->x + tabSize * tab); + } +} + +template +typename TagProcessorBase::Operation TagProcessorBase::Process(u16 ch, ContextType* pCtx) { + switch (ch) { + case '\n': + ProcessLinefeed(pCtx); + return OPERATION_NEXT_LINE; + case '\t': + ProcessTab(pCtx); + return OPERATION_NO_CHAR_SPACE; + default: + return OPERATION_DEFAULT; + } +} + +template +typename TagProcessorBase::Operation TagProcessorBase::CalcRect(Rect* pRect, u16 ch, ContextType* pCtx) { + switch (ch) { + case '\n': { + TextWriterBase* writer = pCtx->writer; + pRect->right = writer->GetCursorX(); + pRect->top = writer->GetCursorY(); + ProcessLinefeed(pCtx); + pRect->left = writer->GetCursorX(); + pRect->bottom = writer->GetCursorY() + pCtx->writer->GetFontHeight(); + pRect->Normalize(); + return OPERATION_NEXT_LINE; + } + case '\t': { + TextWriterBase* writer = pCtx->writer; + pRect->left = writer->GetCursorX(); + ProcessTab(pCtx); + pRect->right = writer->GetCursorX(); + pRect->top = writer->GetCursorY(); + pRect->bottom = pRect->top + writer->GetFontHeight(); + pRect->Normalize(); + return OPERATION_NO_CHAR_SPACE; + } + default: + return OPERATION_DEFAULT; + } +} + +template class TagProcessorBase; +template class TagProcessorBase; + +} // namespace ut +} // namespace nw4r