mirror of
https://github.com/crosspoint-reader/crosspoint-reader.git
synced 2026-08-13 14:21:57 -07:00
74 lines
3.6 KiB
C++
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);
|
|
}
|