From fa277052a9000dd07eb76fdc48d1280e1476bcd9 Mon Sep 17 00:00:00 2001 From: wangyingfang <132874950+wangyingfang@users.noreply.github.com> Date: Mon, 16 Dec 2024 17:56:30 +0800 Subject: [PATCH] Add bold support for CJK characters (#3069) Co-authored-by: Yingfang Co-authored-by: Bart Louwers --- platform/darwin/src/local_glyph_rasterizer.mm | 31 +++++++- .../ping_fang_with_bold_in_style/expected.png | Bin 0 -> 17912 bytes test/text/local_glyph_rasterizer.test.cpp | 69 ++++++------------ 3 files changed, 48 insertions(+), 52 deletions(-) create mode 100644 test/fixtures/local_glyphs/ping_fang_with_bold_in_style/expected.png diff --git a/platform/darwin/src/local_glyph_rasterizer.mm b/platform/darwin/src/local_glyph_rasterizer.mm index 889b1daaadf..eef0bc31d4c 100644 --- a/platform/darwin/src/local_glyph_rasterizer.mm +++ b/platform/darwin/src/local_glyph_rasterizer.mm @@ -1,8 +1,11 @@ #include #include +#include #include #include +#include + #include #import @@ -191,16 +194,28 @@ CFDictionaryRefHandle attributes( @param font The font to apply to the codepoint. @param metrics Upon return, the metrics match the font’s metrics for the glyph representing the codepoint. + @param isBold use kCTFontBoldTrait if it is true. @returns An image containing the glyph. */ -PremultipliedImage drawGlyphBitmap(GlyphID glyphID, CTFontRef font, GlyphMetrics& metrics) { +PremultipliedImage drawGlyphBitmap(GlyphID glyphID, CTFontRef font, GlyphMetrics& metrics, BOOL isBold) { CFStringRefHandle string(CFStringCreateWithCharacters(NULL, reinterpret_cast(&glyphID), 1)); if (!string) { throw std::runtime_error("Unable to create string from codepoint"); } + // Create a bold variant of the font + CTFontRefHandle boldFont(CTFontCreateCopyWithSymbolicTraits(font, 0.0, NULL, kCTFontBoldTrait, kCTFontBoldTrait)); + if (!boldFont) { + CFStringRefHandle familyNameHandle(CTFontCopyFamilyName(font)); + NSString* familyName = (__bridge NSString *)(*familyNameHandle); + std::string stdFamilyName(familyName.UTF8String); + Log::Error(Event::General, "Unable to create bold font for " + stdFamilyName); + } + + CTFontRef drawFont = isBold && boldFont ? *boldFont : font; + CFStringRef keys[] = { kCTFontAttributeName }; - CFTypeRef values[] = { font }; + CFTypeRef values[] = { drawFont }; CFDictionaryRefHandle attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys, @@ -265,7 +280,7 @@ CGContextHandle context(CGBitmapContextCreate( CGContextSetTextPosition(*context, 0.0, descent); CTLineDraw(*line, *context); - + return rgbaBitmap; } @@ -288,8 +303,16 @@ CGContextHandle context(CGBitmapContextCreate( } manufacturedGlyph.id = glyphID; + BOOL isBold = NO; + // Only check the first font name to detect if the user prefers using bold + if (!fontStack.empty()) { + std::string lowercaseFont = platform::lowercase(fontStack.front()); + if (lowercaseFont.find("bold") != std::string::npos && lowercaseFont.find("semibold") == std::string::npos) { + isBold = YES; + } + } - PremultipliedImage rgbaBitmap = drawGlyphBitmap(glyphID, *font, manufacturedGlyph.metrics); + PremultipliedImage rgbaBitmap = drawGlyphBitmap(glyphID, *font, manufacturedGlyph.metrics, isBold); Size size(manufacturedGlyph.metrics.width, manufacturedGlyph.metrics.height); // Copy alpha values from RGBA bitmap into the AlphaImage output diff --git a/test/fixtures/local_glyphs/ping_fang_with_bold_in_style/expected.png b/test/fixtures/local_glyphs/ping_fang_with_bold_in_style/expected.png new file mode 100644 index 0000000000000000000000000000000000000000..3de939b478752519d15009b0e599214f22765010 GIT binary patch literal 17912 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 M)78&qol`;+05dZGSO5S3 literal 0 HcmV?d00001 diff --git a/test/text/local_glyph_rasterizer.test.cpp b/test/text/local_glyph_rasterizer.test.cpp index 8e3235791c5..1922aacd97c 100644 --- a/test/text/local_glyph_rasterizer.test.cpp +++ b/test/text/local_glyph_rasterizer.test.cpp @@ -10,6 +10,8 @@ #include #include +#include + /* LoadLocalCJKGlyph in glyph_manager.test.cpp exercises the platform-independent part of LocalGlyphRasterizer. This test actually @@ -17,13 +19,8 @@ on. Different platforms have different default fonts, so adding a new platform requires new "expected" fixtures. - At the time of writing, we don't run `mbgl-test` on iOS or Android, so the - only supported test platform is macOS. Supporting Android would require - adding a new test case (probably using the "Droid" font family). iOS should - theoretically work -- the "PingFang" font family used below is expected to be - available on all iOS devices, and we use a relatively high image diff - tolerance (0.05) to account for small changes between the many possible - variants of the PingFang family. + At the time of writing, we don't run this test on Android, that would require + adding a new test case (probably using the "Droid" font family). */ using namespace mbgl; @@ -33,7 +30,14 @@ namespace { class LocalGlyphRasterizerTest { public: LocalGlyphRasterizerTest(const std::optional fontFamily) - : frontend(1, gfx::HeadlessBackend::SwapBehaviour::NoFlush, gfx::ContextMode::Unique, fontFamily) {} + : frontend(1, gfx::HeadlessBackend::SwapBehaviour::NoFlush, gfx::ContextMode::Unique, fontFamily) { + this->fileSource->glyphsResponse = [&](const Resource& resource) { + EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); + Response response; + response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); + return response; + }; + } util::RunLoop loop; std::shared_ptr fileSource = std::make_shared(); @@ -59,12 +63,6 @@ class LocalGlyphRasterizerTest { TEST(LocalGlyphRasterizer, PingFang) { LocalGlyphRasterizerTest test(std::string("PingFang TC")); - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); #if defined(__APPLE__) && !defined(__QT__) test.checkRendering("ping_fang", 0.0161); @@ -73,16 +71,19 @@ TEST(LocalGlyphRasterizer, PingFang) { #endif // defined(__APPLE__) } +TEST(LocalGlyphRasterizer, PingFangWithBoldInStyle) { + LocalGlyphRasterizerTest test(std::string("PingFang TC")); + std::stringstream ss; + ss << std::regex_replace( + util::read_file("test/fixtures/local_glyphs/mixed.json"), std::regex("NotoCJK"), "NotoCJK Bold"); + test.map.getStyle().loadJSON(ss.str()); + test.checkRendering("ping_fang_with_bold_in_style"); +} + #if !defined(__QT__) TEST(LocalGlyphRasterizer, PingFangSemibold) { LocalGlyphRasterizerTest test(std::string("PingFang TC Semibold")); - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); test.checkRendering("ping_fang_semibold", 0.0161); } @@ -94,13 +95,6 @@ TEST(LocalGlyphRasterizer, PingFangSemibold) { TEST(LocalGlyphRasterizer, NotoSansCJK) { LocalGlyphRasterizerTest test(std::string("Noto Sans CJK KR Regular")); - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; - test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); test.checkRendering("noto_sans_cjk_kr_regular_qt"); } @@ -110,13 +104,6 @@ TEST(LocalGlyphRasterizer, NoLocal) { // Expectation: without any local fonts set, and without any CJK glyphs // provided, the output should just contain basic latin characters. LocalGlyphRasterizerTest test({}); - - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); test.checkRendering("no_local", 0.001, 0.1); } @@ -126,13 +113,6 @@ TEST(LocalGlyphRasterizer, NoLocalWithContentInsets) { // center. Rendered text should be on the same offset and keep the same size // as with no offset. LocalGlyphRasterizerTest test({}); - - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; auto viewSize = test.frontend.getSize(); test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); @@ -149,13 +129,6 @@ TEST(LocalGlyphRasterizer, NoLocalWithContentInsetsAndPitch) { // center. Rendered text should be on the same offset and keep the same size // as with no offset. LocalGlyphRasterizerTest test({}); - - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; auto viewSize = test.frontend.getSize(); test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json"));