Files

74 lines
3.6 KiB
C++

#include <gtest/gtest.h>
#include "lib/EpdFont/EpdFontData.h"
// ============================================================================
// Anchor selection and placement for combining marks without GPOS tables.
//
// Hebrew niqqud whose identity depends on position must not use the default
// centre-and-raise heuristic: dagesh sits inside the letter body, the
// shin/sin dots sit over the letter's right/left arm, and holam hangs over
// the left corner (see PR #2541 review feedback).
// ============================================================================
using combiningMark::Anchor;
using combiningMark::anchorFor;
using combiningMark::anchorOver;
using combiningMark::anchorOverRotated90CW;
using combiningMark::raiseAboveBase;
TEST(AnchorFor, PositionSensitiveNiqqud) {
EXPECT_EQ(anchorFor(0x05BC), Anchor::CenterNative); // dagesh/mapiq
EXPECT_EQ(anchorFor(0x05BA), Anchor::CenterNative); // holam haser for vav
EXPECT_EQ(anchorFor(0x05C1), Anchor::RightNative); // shin dot
EXPECT_EQ(anchorFor(0x05C2), Anchor::LeftNative); // sin dot
EXPECT_EQ(anchorFor(0x05B9), Anchor::LeftNative); // holam
}
TEST(AnchorFor, EverythingElseKeepsCentreRaisedDefault) {
EXPECT_EQ(anchorFor(0x05B0), Anchor::CenterRaised); // Hebrew sheva
EXPECT_EQ(anchorFor(0x05B7), Anchor::CenterRaised); // Hebrew patach
EXPECT_EQ(anchorFor(0x064E), Anchor::CenterRaised); // Arabic fatha
EXPECT_EQ(anchorFor(0x0651), Anchor::CenterRaised); // Arabic shadda
EXPECT_EQ(anchorFor(0x0301), Anchor::CenterRaised); // combining acute
}
// Base glyph: cursor 100, left 1, width 12. Mark: left 2, width 4.
TEST(AnchorOver, HorizontalPlacementPerAnchor) {
// Centered: base bitmap spans [101, 113), centre 107; mark starts at 105.
EXPECT_EQ(anchorOver(Anchor::CenterRaised, 100, 1, 12, 2, 4), 105 - 2);
EXPECT_EQ(anchorOver(Anchor::CenterNative, 100, 1, 12, 2, 4), 105 - 2);
// Left-aligned: mark bitmap starts at the base bitmap's left edge (101).
EXPECT_EQ(anchorOver(Anchor::LeftNative, 100, 1, 12, 2, 4), 101 - 2);
// Right-aligned: mark bitmap ends at the base bitmap's right edge (113).
EXPECT_EQ(anchorOver(Anchor::RightNative, 100, 1, 12, 2, 4), 109 - 2);
}
// The rotated coordinate system inverts every left/width term, so the mark's
// offset from the base cursor must be the exact mirror of the unrotated one.
TEST(AnchorOverRotated90CW, MirrorsUnrotatedOffsets) {
for (const Anchor anchor : {Anchor::CenterRaised, Anchor::CenterNative, Anchor::LeftNative, Anchor::RightNative}) {
const int offset = anchorOver(anchor, 100, 1, 12, 2, 4) - 100;
EXPECT_EQ(anchorOverRotated90CW(anchor, 100, 1, 12, 2, 4), 100 - offset);
}
}
TEST(RaiseAboveBase, NativeAnchorsKeepFontDesignedHeight) {
// A dagesh-like dot designed inside the letter body (top 8 of a base whose
// top is 12) must NOT be hoisted above the letter.
EXPECT_EQ(raiseAboveBase(Anchor::CenterNative, 8, 3, 12), 0);
// Shin/sin dots overlapping the letter's top must not be pushed clear.
EXPECT_EQ(raiseAboveBase(Anchor::RightNative, 13, 3, 12), 0);
EXPECT_EQ(raiseAboveBase(Anchor::LeftNative, 13, 3, 12), 0);
}
TEST(RaiseAboveBase, CentreRaisedBehaviourUnchanged) {
// Above-baseline mark colliding with the base: raised to restore a 1px gap.
// gap = markTop - markHeight - baseTop = 10 - 3 - 12 = -5 -> raise 6.
EXPECT_EQ(raiseAboveBase(Anchor::CenterRaised, 10, 3, 12), 6);
// Already clear of the base: no raise.
EXPECT_EQ(raiseAboveBase(Anchor::CenterRaised, 16, 3, 12), 0);
// Below-baseline mark (kasra, cedilla): stays at font-native position.
EXPECT_EQ(raiseAboveBase(Anchor::CenterRaised, 2, 4, 12), 0);
}