feat(core): render local CJK glyphs at 2x texture resolution (#4304)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bart Louwers <bart@emeel.net>
This commit is contained in:
Taku Fukada
2026-07-01 20:52:01 +09:00
committed by GitHub
parent 60f15190c3
commit 887e6021e6
22 changed files with 357 additions and 84 deletions

View File

@@ -10,6 +10,55 @@
using namespace mbgl;
using namespace mbgl::style;
// Atlas padding is not scaled with textureScale, so a 2x glyph quad is 1
// logical pixel smaller than its 1x equivalent. GL JS-style fractional metrics
// keep its center aligned with the 1x quad.
TEST(getGlyphQuads, DoubleResolutionGlyphPreservesLogicalQuadSize) {
GlyphMetrics metrics1x;
metrics1x.width = 24;
metrics1x.height = 24;
metrics1x.left = 0;
metrics1x.top = -8;
metrics1x.advance = 24;
metrics1x.isDoubleResolution = false;
GlyphMetrics metrics2x = metrics1x;
metrics2x.left += 0.5f;
metrics2x.top -= 0.5f;
metrics2x.isDoubleResolution = true;
// Rects reflect the real DynamicTextureAtlas output: bitmap.size + 2 *
// ImagePosition::padding (= 2). 1x bitmap 30 -> rect 32; 2x bitmap 60 -> rect 62.
Shaping shapedText1x;
shapedText1x.positionedLines.emplace_back();
shapedText1x.positionedLines.back().positionedGlyphs.emplace_back(
PositionedGlyph(u'A', 0.0f, 0.0f, false, 0, 1.0f, Rect<uint16_t>(0, 0, 32, 32), metrics1x, std::nullopt));
Shaping shapedText2x;
shapedText2x.positionedLines.emplace_back();
shapedText2x.positionedLines.back().positionedGlyphs.emplace_back(
PositionedGlyph(u'A', 0.0f, 0.0f, false, 0, 1.0f, Rect<uint16_t>(0, 0, 62, 62), metrics2x, std::nullopt));
SymbolLayoutProperties::Evaluated layout;
SymbolQuads quads1x = getGlyphQuads(shapedText1x, {{0, 0}}, layout, SymbolPlacementType::Point, {}, false);
SymbolQuads quads2x = getGlyphQuads(shapedText2x, {{0, 0}}, layout, SymbolPlacementType::Point, {}, false);
ASSERT_EQ(quads1x.size(), 1u);
ASSERT_EQ(quads2x.size(), 1u);
// The 2x quad is 1 logical pixel smaller, and shifted by 0.5px to keep the
// same center as the 1x quad.
EXPECT_FLOAT_EQ(quads1x[0].tl.x + 0.5f, quads2x[0].tl.x);
EXPECT_FLOAT_EQ(quads1x[0].tl.y + 0.5f, quads2x[0].tl.y);
EXPECT_FLOAT_EQ(quads1x[0].br.x - 0.5f, quads2x[0].br.x);
EXPECT_FLOAT_EQ(quads1x[0].br.y - 0.5f, quads2x[0].br.y);
EXPECT_FLOAT_EQ(quads1x[0].br.x - quads1x[0].tl.x, 32.0f);
EXPECT_FLOAT_EQ(quads2x[0].br.x - quads2x[0].tl.x, 31.0f);
EXPECT_FLOAT_EQ(quads1x[0].br.y - quads1x[0].tl.y, 32.0f);
EXPECT_FLOAT_EQ(quads2x[0].br.y - quads2x[0].tl.y, 31.0f);
}
TEST(getIconQuads, normal) {
SymbolLayoutProperties::Evaluated layout;
Anchor anchor(2.0, 3.0, 0.0, 0);