Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Bart Louwers <bart@emeel.net>
326 lines
13 KiB
C++
326 lines
13 KiB
C++
#include <mbgl/geometry/anchor.hpp>
|
|
#include <mbgl/layout/symbol_instance.hpp>
|
|
#include <mbgl/style/image_impl.hpp>
|
|
#include <mbgl/style/layers/symbol_layer_properties.hpp>
|
|
#include <mbgl/test/util.hpp>
|
|
#include <mbgl/text/glyph.hpp>
|
|
#include <mbgl/text/quads.hpp>
|
|
#include <mbgl/text/shaping.hpp>
|
|
|
|
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);
|
|
ImagePosition image = {Rect<uint16_t>(0, 0, 15, 11), style::Image::Impl("test", PremultipliedImage({1, 1}), 1.0f)};
|
|
|
|
auto shapedIcon = PositionedIcon::shapeIcon(image, {{-6.5f, -4.5f}}, SymbolAnchorType::Center);
|
|
|
|
GeometryCoordinates line;
|
|
|
|
SymbolQuads quads = getIconQuads(shapedIcon, 0, SymbolContent::IconRGBA, false);
|
|
|
|
ASSERT_EQ(quads.size(), 1);
|
|
const auto& quad = quads[0];
|
|
EXPECT_FLOAT_EQ(quad.tl.x, -14);
|
|
EXPECT_FLOAT_EQ(quad.tl.y, -10);
|
|
EXPECT_FLOAT_EQ(quad.tr.x, 1);
|
|
EXPECT_FLOAT_EQ(quad.tr.y, -10);
|
|
EXPECT_FLOAT_EQ(quad.bl.x, -14);
|
|
EXPECT_FLOAT_EQ(quad.bl.y, 1);
|
|
EXPECT_FLOAT_EQ(quad.br.x, 1);
|
|
EXPECT_FLOAT_EQ(quad.br.y, 1);
|
|
}
|
|
|
|
TEST(getIconQuads, style) {
|
|
Anchor anchor(0.0, 0.0, 0.0, 0);
|
|
const ImagePosition image = {Rect<uint16_t>(0, 0, 20, 20),
|
|
style::Image::Impl("test", PremultipliedImage({1, 1}), 1.0f)};
|
|
|
|
GeometryCoordinates line;
|
|
Shaping shapedText;
|
|
shapedText.top = -10.0f;
|
|
shapedText.bottom = 30.0f;
|
|
shapedText.left = -60.0f;
|
|
shapedText.right = 20.0f;
|
|
// shapedText.positionedGlyphs.emplace_back(PositionedGlyph(32, 0.0f, 0.0f, false, 0, 1.0));
|
|
shapedText.positionedLines.emplace_back();
|
|
shapedText.positionedLines.back().positionedGlyphs.emplace_back(PositionedGlyph(32,
|
|
0.0f,
|
|
0.0f,
|
|
false,
|
|
0,
|
|
1.0,
|
|
/*texRect*/ {},
|
|
/*metrics*/ {},
|
|
/*imageID*/ std::nullopt));
|
|
|
|
// none
|
|
{
|
|
auto shapedIcon = PositionedIcon::shapeIcon(image, {{-9.5f, -9.5f}}, SymbolAnchorType::Center);
|
|
|
|
EXPECT_FLOAT_EQ(-18.5f, shapedIcon.top());
|
|
EXPECT_FLOAT_EQ(-0.5f, shapedIcon.right());
|
|
EXPECT_FLOAT_EQ(-0.5f, shapedIcon.bottom());
|
|
EXPECT_FLOAT_EQ(-18.5f, shapedIcon.left());
|
|
|
|
SymbolLayoutProperties::Evaluated layout;
|
|
SymbolQuads quads = getIconQuads(shapedIcon, 0, SymbolContent::IconRGBA, false);
|
|
|
|
ASSERT_EQ(quads.size(), 1);
|
|
const auto& quad = quads[0];
|
|
|
|
EXPECT_FLOAT_EQ(quad.tl.x, -19.5);
|
|
EXPECT_FLOAT_EQ(quad.tl.y, -19.5);
|
|
EXPECT_FLOAT_EQ(quad.tr.x, 0.5);
|
|
EXPECT_FLOAT_EQ(quad.tr.y, -19.5);
|
|
EXPECT_FLOAT_EQ(quad.bl.x, -19.5);
|
|
EXPECT_FLOAT_EQ(quad.bl.y, 0.5);
|
|
EXPECT_FLOAT_EQ(quad.br.x, 0.5);
|
|
EXPECT_FLOAT_EQ(quad.br.y, 0.5);
|
|
}
|
|
|
|
// width
|
|
{
|
|
auto shapedIcon = PositionedIcon::shapeIcon(image, {{-9.5f, -9.5f}}, SymbolAnchorType::Center);
|
|
shapedIcon.fitIconToText(shapedText, IconTextFitType::Width, {{0, 0, 0, 0}}, {{0, 0}}, 24.0f / 24.0f);
|
|
SymbolQuads quads = getIconQuads(shapedIcon, 0, SymbolContent::IconRGBA, false);
|
|
|
|
ASSERT_EQ(quads.size(), 1);
|
|
const auto& quad = quads[0];
|
|
|
|
EXPECT_FLOAT_EQ(quad.tl.x, -64.4444427f);
|
|
EXPECT_FLOAT_EQ(quad.tl.y, 0);
|
|
EXPECT_FLOAT_EQ(quad.tr.x, 24.4444427f);
|
|
EXPECT_FLOAT_EQ(quad.tr.y, 0);
|
|
EXPECT_FLOAT_EQ(quad.bl.x, -64.4444427f);
|
|
EXPECT_FLOAT_EQ(quad.bl.y, 20);
|
|
EXPECT_FLOAT_EQ(quad.br.x, 24.4444427f);
|
|
EXPECT_FLOAT_EQ(quad.br.y, 20);
|
|
}
|
|
|
|
// width x textSize
|
|
{
|
|
auto shapedIcon = PositionedIcon::shapeIcon(image, {{-9.5f, -9.5f}}, SymbolAnchorType::Center);
|
|
shapedIcon.fitIconToText(shapedText, IconTextFitType::Width, {{0, 0, 0, 0}}, {{0, 0}}, 12.0f / 24.0f);
|
|
SymbolQuads quads = getIconQuads(shapedIcon, 0, SymbolContent::IconRGBA, false);
|
|
|
|
ASSERT_EQ(quads.size(), 1);
|
|
const auto& quad = quads[0];
|
|
|
|
EXPECT_FLOAT_EQ(quad.tl.x, -32.2222214f);
|
|
EXPECT_FLOAT_EQ(quad.tl.y, -5);
|
|
EXPECT_FLOAT_EQ(quad.tr.x, 12.2222214f);
|
|
EXPECT_FLOAT_EQ(quad.tr.y, -5);
|
|
EXPECT_FLOAT_EQ(quad.bl.x, -32.2222214f);
|
|
EXPECT_FLOAT_EQ(quad.bl.y, 15);
|
|
EXPECT_FLOAT_EQ(quad.br.x, 12.2222214f);
|
|
EXPECT_FLOAT_EQ(quad.br.y, 15);
|
|
}
|
|
|
|
// width x textSize + padding
|
|
{
|
|
auto shapedIcon = PositionedIcon::shapeIcon(image, {{-9.5f, -9.5f}}, SymbolAnchorType::Center);
|
|
shapedIcon.fitIconToText(shapedText, IconTextFitType::Width, {{5, 10, 5, 10}}, {{0, 0}}, 12.0f / 24.0f);
|
|
SymbolQuads quads = getIconQuads(shapedIcon, 0, SymbolContent::IconRGBA, false);
|
|
|
|
ASSERT_EQ(quads.size(), 1);
|
|
const auto& quad = quads[0];
|
|
|
|
EXPECT_FLOAT_EQ(quad.tl.x, -43.3333321f);
|
|
EXPECT_FLOAT_EQ(quad.tl.y, -5);
|
|
EXPECT_FLOAT_EQ(quad.tr.x, 23.3333321f);
|
|
EXPECT_FLOAT_EQ(quad.tr.y, -5);
|
|
EXPECT_FLOAT_EQ(quad.bl.x, -43.3333321f);
|
|
EXPECT_FLOAT_EQ(quad.bl.y, 15);
|
|
EXPECT_FLOAT_EQ(quad.br.x, 23.3333321f);
|
|
EXPECT_FLOAT_EQ(quad.br.y, 15);
|
|
}
|
|
|
|
// height
|
|
{
|
|
auto shapedIcon = PositionedIcon::shapeIcon(image, {{-9.5f, -9.5f}}, SymbolAnchorType::Center);
|
|
shapedIcon.fitIconToText(shapedText, IconTextFitType::Height, {{0, 0, 0, 0}}, {{0, 0}}, 24.0f / 24.0f);
|
|
SymbolQuads quads = getIconQuads(shapedIcon, 0, SymbolContent::IconRGBA, false);
|
|
|
|
ASSERT_EQ(quads.size(), 1);
|
|
const auto& quad = quads[0];
|
|
|
|
EXPECT_FLOAT_EQ(quad.tl.x, -30);
|
|
EXPECT_FLOAT_EQ(quad.tl.y, -12.2222214f);
|
|
EXPECT_FLOAT_EQ(quad.tr.x, -10);
|
|
EXPECT_FLOAT_EQ(quad.tr.y, -12.2222214f);
|
|
EXPECT_FLOAT_EQ(quad.bl.x, -30);
|
|
EXPECT_FLOAT_EQ(quad.bl.y, 32.2222214f);
|
|
EXPECT_FLOAT_EQ(quad.br.x, -10);
|
|
EXPECT_FLOAT_EQ(quad.br.y, 32.2222214f);
|
|
}
|
|
|
|
// height x textSize
|
|
{
|
|
SymbolLayoutProperties::Evaluated layout;
|
|
auto shapedIcon = PositionedIcon::shapeIcon(image, {{-9.5f, -9.5f}}, SymbolAnchorType::Center);
|
|
shapedIcon.fitIconToText(shapedText, IconTextFitType::Height, {{0, 0, 0, 0}}, {{0, 0}}, 12.0f / 24.0f);
|
|
SymbolQuads quads = getIconQuads(shapedIcon, 0, SymbolContent::IconRGBA, false);
|
|
|
|
ASSERT_EQ(quads.size(), 1);
|
|
const auto& quad = quads[0];
|
|
|
|
EXPECT_FLOAT_EQ(quad.tl.x, -20);
|
|
EXPECT_FLOAT_EQ(quad.tl.y, -6.11111069f);
|
|
EXPECT_FLOAT_EQ(quad.tr.x, 0);
|
|
EXPECT_FLOAT_EQ(quad.tr.y, -6.11111069f);
|
|
EXPECT_FLOAT_EQ(quad.bl.x, -20);
|
|
EXPECT_FLOAT_EQ(quad.bl.y, 16.1111107f);
|
|
EXPECT_FLOAT_EQ(quad.br.x, 0);
|
|
EXPECT_FLOAT_EQ(quad.br.y, 16.1111107f);
|
|
}
|
|
|
|
// height x textSize + padding
|
|
{
|
|
auto shapedIcon = PositionedIcon::shapeIcon(image, {{-9.5f, -9.5f}}, SymbolAnchorType::Center);
|
|
shapedIcon.fitIconToText(shapedText, IconTextFitType::Height, {{5, 10, 5, 20}}, {{0, 0}}, 12.0f / 24.0f);
|
|
SymbolQuads quads = getIconQuads(shapedIcon, 0, SymbolContent::IconRGBA, false);
|
|
|
|
ASSERT_EQ(quads.size(), 1);
|
|
const auto& quad = quads[0];
|
|
|
|
EXPECT_FLOAT_EQ(quad.tl.x, -20);
|
|
EXPECT_FLOAT_EQ(quad.tl.y, -11.666666f);
|
|
EXPECT_FLOAT_EQ(quad.tr.x, 0);
|
|
EXPECT_FLOAT_EQ(quad.tr.y, -11.666666f);
|
|
EXPECT_FLOAT_EQ(quad.bl.x, -20);
|
|
EXPECT_FLOAT_EQ(quad.bl.y, 21.666666f);
|
|
EXPECT_FLOAT_EQ(quad.br.x, 0);
|
|
EXPECT_FLOAT_EQ(quad.br.y, 21.666666f);
|
|
}
|
|
|
|
// both
|
|
{
|
|
auto shapedIcon = PositionedIcon::shapeIcon(image, {{-9.5f, -9.5f}}, SymbolAnchorType::Center);
|
|
shapedIcon.fitIconToText(shapedText, IconTextFitType::Both, {{0, 0, 0, 0}}, {{0, 0}}, 24.0f / 24.0f);
|
|
SymbolQuads quads = getIconQuads(shapedIcon, 0, SymbolContent::IconRGBA, false);
|
|
|
|
ASSERT_EQ(quads.size(), 1);
|
|
const auto& quad = quads[0];
|
|
|
|
EXPECT_FLOAT_EQ(quad.tl.x, -64.4444427f);
|
|
EXPECT_FLOAT_EQ(quad.tl.y, -12.2222214f);
|
|
EXPECT_FLOAT_EQ(quad.tr.x, 24.4444427f);
|
|
EXPECT_FLOAT_EQ(quad.tr.y, -12.2222214f);
|
|
EXPECT_FLOAT_EQ(quad.bl.x, -64.4444427f);
|
|
EXPECT_FLOAT_EQ(quad.bl.y, 32.2222214f);
|
|
EXPECT_FLOAT_EQ(quad.br.x, 24.4444427f);
|
|
EXPECT_FLOAT_EQ(quad.br.y, 32.2222214f);
|
|
}
|
|
|
|
// both x textSize
|
|
{
|
|
auto shapedIcon = PositionedIcon::shapeIcon(image, {{-9.5f, -9.5f}}, SymbolAnchorType::Center);
|
|
shapedIcon.fitIconToText(shapedText, IconTextFitType::Both, {{0, 0, 0, 0}}, {{0, 0}}, 12.0f / 24.0f);
|
|
SymbolQuads quads = getIconQuads(shapedIcon, 0, SymbolContent::IconRGBA, false);
|
|
|
|
ASSERT_EQ(quads.size(), 1);
|
|
const auto& quad = quads[0];
|
|
|
|
EXPECT_FLOAT_EQ(quad.tl.x, -32.2222214f);
|
|
EXPECT_FLOAT_EQ(quad.tl.y, -6.11111069f);
|
|
EXPECT_FLOAT_EQ(quad.tr.x, 12.2222214f);
|
|
EXPECT_FLOAT_EQ(quad.tr.y, -6.11111069f);
|
|
EXPECT_FLOAT_EQ(quad.bl.x, -32.2222214f);
|
|
EXPECT_FLOAT_EQ(quad.bl.y, 16.1111107f);
|
|
EXPECT_FLOAT_EQ(quad.br.x, 12.2222214f);
|
|
EXPECT_FLOAT_EQ(quad.br.y, 16.1111107f);
|
|
}
|
|
|
|
// both x textSize + padding
|
|
{
|
|
auto shapedIcon = PositionedIcon::shapeIcon(image, {{-9.5f, -9.5f}}, SymbolAnchorType::Center);
|
|
shapedIcon.fitIconToText(shapedText, IconTextFitType::Both, {{5, 10, 5, 10}}, {{0, 0}}, 12.0f / 24.0f);
|
|
SymbolQuads quads = getIconQuads(shapedIcon, 0, SymbolContent::IconRGBA, false);
|
|
|
|
ASSERT_EQ(quads.size(), 1);
|
|
const auto& quad = quads[0];
|
|
|
|
EXPECT_FLOAT_EQ(quad.tl.x, -43.3333321f);
|
|
EXPECT_FLOAT_EQ(quad.tl.y, -11.666666f);
|
|
EXPECT_FLOAT_EQ(quad.tr.x, 23.3333321f);
|
|
EXPECT_FLOAT_EQ(quad.tr.y, -11.666666f);
|
|
EXPECT_FLOAT_EQ(quad.bl.x, -43.3333321f);
|
|
EXPECT_FLOAT_EQ(quad.bl.y, 21.666666f);
|
|
EXPECT_FLOAT_EQ(quad.br.x, 23.3333321f);
|
|
EXPECT_FLOAT_EQ(quad.br.y, 21.666666f);
|
|
}
|
|
|
|
// both x textSize + padding t/r/b/l
|
|
{
|
|
SymbolLayoutProperties::Evaluated layout;
|
|
layout.get<TextSize>() = 12.0f;
|
|
auto shapedIcon = PositionedIcon::shapeIcon(image, {{-9.5f, -9.5f}}, SymbolAnchorType::Center);
|
|
shapedIcon.fitIconToText(shapedText, IconTextFitType::Both, {{0, 5, 10, 15}}, {{0, 0}}, 12.0f / 24.0f);
|
|
SymbolQuads quads = getIconQuads(shapedIcon, 0, SymbolContent::IconRGBA, false);
|
|
|
|
ASSERT_EQ(quads.size(), 1);
|
|
const auto& quad = quads[0];
|
|
|
|
EXPECT_FLOAT_EQ(quad.tl.x, -48.3333321f);
|
|
EXPECT_FLOAT_EQ(quad.tl.y, -6.66666603f);
|
|
EXPECT_FLOAT_EQ(quad.tr.x, 18.3333321f);
|
|
EXPECT_FLOAT_EQ(quad.tr.y, -6.66666603f);
|
|
EXPECT_FLOAT_EQ(quad.bl.x, -48.3333321f);
|
|
EXPECT_FLOAT_EQ(quad.bl.y, 26.666666f);
|
|
EXPECT_FLOAT_EQ(quad.br.x, 18.3333321f);
|
|
EXPECT_FLOAT_EQ(quad.br.y, 26.666666f);
|
|
}
|
|
}
|