#include "fonts_test_helpers.hpp" namespace pdfengine::fonts { TEST(FontLoaderTest, FontFaceLoadFromMemorySuccess) { std::string fontPath = getSystemFontPath(); if (fontPath.empty()) { GTEST_SKIP() << "No system font found to run load from memory success test."; } std::ifstream file(fontPath, std::ios::binary | std::ios::ate); ASSERT_TRUE(file.is_open()); std::streamsize size = file.tellg(); file.seekg(0, std::ios::beg); std::vector buffer(size); ASSERT_TRUE(file.read(reinterpret_cast(buffer.data()), size)); FontFace face; ASSERT_TRUE(face.loadFromMemory(buffer)); ASSERT_NE(face.getFace(), nullptr); unsigned int glyphIndex = FT_Get_Char_Index(face.getFace(), 'M'); ASSERT_GT(glyphIndex, 0u); auto glyph = face.renderGlyph(glyphIndex, 16); ASSERT_TRUE(glyph.has_value()); EXPECT_GT(glyph->width, 0); EXPECT_GT(glyph->height, 0); EXPECT_GT(glyph->advance, 0.0); } TEST(FontLoaderTest, FontFaceLoadFromMemoryInvalid) { FontFace face; std::vector emptyData; EXPECT_FALSE(face.loadFromMemory(emptyData)); EXPECT_EQ(face.getFace(), nullptr); std::vector corruptData = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; EXPECT_FALSE(face.loadFromMemory(corruptData)); EXPECT_EQ(face.getFace(), nullptr); } TEST(FontLoaderTest, FontLoaderTrueTypeSuccess) { std::string fontPath = getSystemFontPath(); if (fontPath.empty()) { GTEST_SKIP() << "No system font found to run PDF font loader test."; } std::ifstream file(fontPath, std::ios::binary | std::ios::ate); ASSERT_TRUE(file.is_open()); std::streamsize size = file.tellg(); file.seekg(0, std::ios::beg); std::vector buffer(size); ASSERT_TRUE(file.read(reinterpret_cast(buffer.data()), size)); auto pdfFont = pdfengine::fonts::pdf_fonts::FontLoader::loadTrueTypeFromMemory("Arial", buffer); ASSERT_NE(pdfFont, nullptr); EXPECT_EQ(pdfFont->getBaseFont(), "Arial"); EXPECT_EQ(pdfFont->getType(), pdfengine::fonts::pdf_fonts::FontType::TrueType); EXPECT_TRUE(pdfFont->isEmbedded()); HbShaper shaper; auto glyphs = shaper.shapeRun("Test Memory Load", pdfFont->getFontFace(), 16); EXPECT_FALSE(glyphs.empty()); } TEST(FontDescriptorTest, DescriptorDefaultValues) { pdfengine::fonts::pdf_fonts::FontDescriptor desc; EXPECT_EQ(desc.getFontName(), ""); EXPECT_EQ(desc.getFlags(), 0); EXPECT_EQ(desc.getItalicAngle(), 0.0); EXPECT_EQ(desc.getAscent(), 0.0); EXPECT_EQ(desc.getDescent(), 0.0); EXPECT_EQ(desc.getCapHeight(), 0.0); EXPECT_EQ(desc.getStemV(), 0.0); pdfengine::fonts::pdf_fonts::FontBBox bbox = desc.getFontBBox(); EXPECT_EQ(bbox.llx, 0); EXPECT_EQ(bbox.lly, 0); EXPECT_EQ(bbox.urx, 0); EXPECT_EQ(bbox.ury, 0); EXPECT_FALSE(desc.isFixedPitch()); EXPECT_FALSE(desc.isSerif()); EXPECT_FALSE(desc.isSymbolic()); EXPECT_FALSE(desc.isItalic()); } TEST(FontDescriptorTest, DescriptorParsingSuccess) { std::string dict = "<< /Type /FontDescriptor\n" " /FontName /ArialMT\n" " /Flags 32\n" " /FontBBox [-166 -225 1000 931]\n" " /ItalicAngle 0\n" " /Ascent 905\n" " /Descent -211\n" " /CapHeight 728\n" " /StemV 94\n" ">>"; pdfengine::fonts::pdf_fonts::FontDescriptor desc; ASSERT_TRUE(desc.parseFromDictionaryString(dict)); EXPECT_EQ(desc.getFontName(), "ArialMT"); EXPECT_EQ(desc.getFlags(), 32); pdfengine::fonts::pdf_fonts::FontBBox bbox = desc.getFontBBox(); EXPECT_EQ(bbox.llx, -166); EXPECT_EQ(bbox.lly, -225); EXPECT_EQ(bbox.urx, 1000); EXPECT_EQ(bbox.ury, 931); EXPECT_DOUBLE_EQ(desc.getItalicAngle(), 0.0); EXPECT_DOUBLE_EQ(desc.getAscent(), 905.0); EXPECT_DOUBLE_EQ(desc.getDescent(), -211.0); EXPECT_DOUBLE_EQ(desc.getCapHeight(), 728.0); EXPECT_DOUBLE_EQ(desc.getStemV(), 94.0); EXPECT_FALSE(desc.isFixedPitch()); EXPECT_TRUE(desc.isNonsymbolic()); EXPECT_FALSE(desc.isItalic()); } TEST(FontDescriptorTest, DescriptorParsingMalformed) { pdfengine::fonts::pdf_fonts::FontDescriptor desc; EXPECT_FALSE(desc.parseFromDictionaryString("/Flags 32 >>")); EXPECT_FALSE(desc.parseFromDictionaryString("<< /Flags 32")); EXPECT_FALSE(desc.parseFromDictionaryString("<< /FontBBox [-166 -225] >>")); EXPECT_FALSE(desc.parseFromDictionaryString("<< /Ascent abc >>")); EXPECT_FALSE(desc.parseFromDictionaryString("<< /Ascent >>")); } TEST(FontDescriptorTest, FontLoaderWithDescriptor) { std::string fontPath = getSystemFontPath(); if (fontPath.empty()) { GTEST_SKIP() << "No system font found to run PDF font loader test."; } std::ifstream file(fontPath, std::ios::binary | std::ios::ate); ASSERT_TRUE(file.is_open()); std::streamsize size = file.tellg(); file.seekg(0, std::ios::beg); std::vector buffer(size); ASSERT_TRUE(file.read(reinterpret_cast(buffer.data()), size)); auto descriptor = std::make_unique(); descriptor->setFontName("Arial-BoldMT"); descriptor->setFlags(96); descriptor->setAscent(905.0); descriptor->setDescent(-211.0); auto pdfFont = pdfengine::fonts::pdf_fonts::FontLoader::loadTrueTypeFromMemory("Arial-Bold", buffer, std::move(descriptor)); ASSERT_NE(pdfFont, nullptr); EXPECT_EQ(pdfFont->getBaseFont(), "Arial-Bold"); EXPECT_TRUE(pdfFont->isEmbedded()); const auto* retrievedDesc = pdfFont->getDescriptor(); ASSERT_NE(retrievedDesc, nullptr); EXPECT_EQ(retrievedDesc->getFontName(), "Arial-BoldMT"); EXPECT_EQ(retrievedDesc->getFlags(), 96); EXPECT_TRUE(retrievedDesc->isItalic()); EXPECT_TRUE(retrievedDesc->isNonsymbolic()); EXPECT_DOUBLE_EQ(retrievedDesc->getAscent(), 905.0); EXPECT_DOUBLE_EQ(retrievedDesc->getDescent(), -211.0); } }