// 批次 2V0-g: the 40250 font path (CGraphicText → CGraphicFontTexture → CGraphicDib) over the GDI // emulation in platform/Win32Gdi.cpp, and the code-page conversions CGraphicTextInstance runs text through. // // Needs a system Tahoma (macOS ships /System/Library/Fonts/Supplemental/Tahoma.ttf); exit 77 (ctest // SKIP) without one, unless MT_ASSETS_STRICT=1. #include "EterLib/StdAfx.h" #include "EterLib/GrpText.h" #include "EterLib/GrpTextInstance.h" #include "EterLib/Util.h" #include "EterLib/ResourceManager.h" #include "../src/platform/EterLib/UIRenderCommands.h" #include "../src/platform/UserInterface/UserInterface.h" #include #include #include #include #include static int g_failures = 0; #define CHECK(cond) \ do { \ if (!(cond)) { \ std::fprintf(stderr, "%s:%d: CHECK(%s)\n", __FILE__, __LINE__, #cond); \ ++g_failures; \ } \ } while (0) static void code_pages() { // CP949 "굴림" (B1BC B8B2) → U+AD74 U+B9BC, and back. const char gulim[] = "\xb1\xbc\xb8\xb2"; WCHAR wide[8] = {}; CHECK(MultiByteToWideChar(949, 0, gulim, -1, nullptr, 0) == 3); CHECK(MultiByteToWideChar(949, 0, gulim, -1, wide, 8) == 3); CHECK(wide[0] == 0xAD74 && wide[1] == 0xB9BC && wide[2] == 0); char narrow[8] = {}; CHECK(WideCharToMultiByte(949, 0, wide, -1, narrow, sizeof(narrow), nullptr, nullptr) == 5); CHECK(std::string(narrow) == gulim); // UTF-8 and the Windows size rules: a too-small buffer answers 0. CHECK(MultiByteToWideChar(CP_UTF8, 0, "\xea\xb5\xb4", 3, wide, 8) == 1 && wide[0] == 0xAD74); CHECK(MultiByteToWideChar(CP_UTF8, 0, "abc", 3, wide, 2) == 0); // CP1252 0x80 is the euro sign. CHECK(MultiByteToWideChar(1252, 0, "\x80", 1, wide, 8) == 1 && wide[0] == 0x20AC); // 40250 Util.cpp face table. CHECK(SetDefaultCodePage(949) && std::string(GetDefaultFontFace()) == "GulimChe"); CHECK(GetCharsetFromCodePage(949) == HANGUL_CHARSET); CHECK(SetDefaultCodePage(1252) && std::string(GetDefaultFontFace()) == "Arial"); CHECK(GetDefaultCodePage() == 1252); } static int glyph_quads(float* min_x, float* max_x) { int count = 0; *min_x = 1e9f; *max_x = -1e9f; for (const auto& command : UIRenderCommands()) { if (command.kind != UIRenderCommand::Image || command.text.rfind("mem:", 0) != 0) continue; ++count; for (float x : command.qx) { *min_x = std::fmin(*min_x, x); *max_x = std::fmax(*max_x, x); } } return count; } int main() { const char* strict = std::getenv("MT_ASSETS_STRICT"); const bool is_strict = strict && std::string(strict) == "1"; PackSingletons(); CResourceManager resource_manager; // CResource::Release queues the resource here code_pages(); if (access("/System/Library/Fonts/Supplemental/Tahoma.ttf", 0) != 0) { std::fprintf(stderr, "port_text_test: no system Tahoma\n"); return g_failures ? 1 : (is_strict ? 1 : 77); } // Not in any pack: CResource::Load falls through to OnLoad(0, NULL), as for every 40250 .fnt. CGraphicText* text = new CGraphicText("Tahoma:12.fnt"); text->AddReference(); text->Load(); CHECK(!text->IsEmpty()); CGraphicTextInstance instance; instance.SetTextPointer(text); instance.SetValue("Hello"); instance.Update(); int width = 0, height = 0; instance.GetTextSize(&width, &height); // GDI lays a 12-pixel LOGFONT cell out as Tahoma's win ascent + descent at 10 ppem: 12 rows. CHECK(height == 12); CHECK(width > 20 && width < 40); CHECK(instance.PixelPositionToCharacterPosition(0) == 0); CHECK(instance.PixelPositionToCharacterPosition(width - 1) == 4); CHECK(instance.PixelPositionToCharacterPosition(width + 5) == -1); UIRenderSetSize(800, 600); UIRenderBeginFrame(); instance.SetPosition(100.0f, 50.0f); instance.Render(); float left = 0, right = 0; CHECK(glyph_quads(&left, &right) == 5); CHECK(std::fabs(left - 100.0f) <= 1.5f); // Centred: the text straddles the position. instance.SetHorizonalAlign(CGraphicTextInstance::HORIZONTAL_ALIGN_CENTER); instance.Update(); UIRenderBeginFrame(); instance.Render(); CHECK(glyph_quads(&left, &right) == 5); CHECK(left < 100.0f && right > 100.0f && std::fabs((left + right) * 0.5f - 100.0f) <= 2.0f); // The glyph page has ink. bool inked = false; for (const auto& command : UIRenderCommands()) { UIMemoryTexture page; if (command.text.rfind("mem:", 0) == 0 && UIRenderMemoryTexture(command.text, &page)) for (std::uint32_t argb : page.argb) inked |= (argb >> 24) != 0; } CHECK(inked); instance.Destroy(); text->Release(); if (g_failures) { std::fprintf(stderr, "%d check(s) failed\n", g_failures); return 1; } std::printf("port_text_test: ok\n"); return 0; }