浏览代码

Tests: Add some test coverage for the TTF parser

This is in Tests/LibTTF instead of Tests/LibGfx because Tests/LibGfx
depends on serenity's file system layout and can't run in lagom,
but this new test runs just fine in lagom.
Nico Weber 3 年之前
父节点
当前提交
fd82121319
共有 3 个文件被更改,包括 95 次插入1 次删除
  1. 7 1
      Meta/Lagom/CMakeLists.txt
  2. 7 0
      Tests/LibTTF/CMakeLists.txt
  3. 81 0
      Tests/LibTTF/TestCmap.cpp

+ 7 - 1
Meta/Lagom/CMakeLists.txt

@@ -338,7 +338,7 @@ if (BUILD_LAGOM)
         LIBS LagomTLS
     )
 
-    # GFX
+    # Gfx
     file(GLOB LIBGFX_SOURCES CONFIGURE_DEPENDS "../../Userland/Libraries/LibGfx/*.cpp")
     file(GLOB LIBGFX_TTF_SOURCES CONFIGURE_DEPENDS "../../Userland/Libraries/LibGfx/TrueTypeFont/*.cpp")
     lagom_lib(Gfx gfx
@@ -621,6 +621,12 @@ if (BUILD_LAGOM)
                 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../Tests/LibTLS)
         endforeach()
 
+        # TTF
+        file(GLOB LIBTTF_TESTS CONFIGURE_DEPENDS "../../Tests/LibTTF/*.cpp")
+        foreach(source ${LIBTTF_TESTS})
+            lagom_test(${source} LIBS LagomGfx)
+        endforeach()
+
         # TimeZone
         file(GLOB LIBTIMEZONE_TEST_SOURCES CONFIGURE_DEPENDS "../../Tests/LibTimeZone/*.cpp")
         foreach(source ${LIBTIMEZONE_TEST_SOURCES})

+ 7 - 0
Tests/LibTTF/CMakeLists.txt

@@ -0,0 +1,7 @@
+set(TEST_SOURCES
+    TestCmap.cpp
+)
+
+foreach(source IN LISTS TEST_SOURCES)
+    serenity_test("${source}" LibGfx)
+endforeach()

+ 81 - 0
Tests/LibTTF/TestCmap.cpp

@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2022, Nico Weber <thakis@chromium.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibGfx/TrueTypeFont/Cmap.h>
+#include <LibTest/TestCase.h>
+
+TEST_CASE(test_cmap_format_4)
+{
+    // clang-format off
+    // Big endian.
+    u8 cmap_table[] =
+    {
+        // https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#cmap-header
+        0, 0,  // uint16 version
+        0, 1,  // uint16 numTables
+
+        // https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#encoding-records-and-encodings
+        0, 0,  // uint16 platformID, 0 means "Unicode"
+        0, 3,  // uint16 encodingID, 3 means "BMP only" for platformID==0.
+        0, 0, 0, 12,  // Offset32 to encoding subtable.
+
+        // https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-4-segment-mapping-to-delta-values
+        0, 4,  // uint16 format = 4
+        0, 42,  // uint16 length in bytes
+        0, 0,  // uint16 language, must be 0
+        0, 6,  // segCount * 2
+        0, 4,  // searchRange
+        0, 1,  // entrySelector
+        0, 2,  // rangeShift
+
+        // endCode array, last entry must be 0xffff.
+        0, 128,
+        1, 0,
+        0xff, 0xff,
+
+        0, 0,  // uint16 reservedPad
+
+        // startCode array
+        0, 16,
+        1, 0,
+        0xff, 0xff,
+
+        // delta array
+        0, 0,
+        0, 10,
+        0, 0,
+
+        // glyphID array
+        0, 0,
+        0, 0,
+        0, 0,
+    };
+    // clang-format on
+    auto cmap = TTF::Cmap::from_slice({ cmap_table, sizeof cmap_table }).value();
+    cmap.set_active_index(0);
+
+    // Format 4 can't handle code points > 0xffff.
+
+    // First range is 16..128.
+    EXPECT_EQ(cmap.glyph_id_for_code_point(15), 0u);
+    EXPECT_EQ(cmap.glyph_id_for_code_point(16), 16u);
+    EXPECT_EQ(cmap.glyph_id_for_code_point(128), 128u);
+    EXPECT_EQ(cmap.glyph_id_for_code_point(129), 0u);
+
+    // Second range is 256..256, with delta 10.
+    EXPECT_EQ(cmap.glyph_id_for_code_point(255), 0u);
+    EXPECT_EQ(cmap.glyph_id_for_code_point(256), 266u);
+    EXPECT_EQ(cmap.glyph_id_for_code_point(257), 0u);
+
+    // Third range is 0xffff..0xffff.
+    // From https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-4-segment-mapping-to-delta-values:
+    // "the final start code and endCode values must be 0xFFFF. This segment need not contain any valid mappings.
+    // (It can just map the single character code 0xFFFF to missingGlyph). However, the segment must be present."
+    // FIXME: Make TTF::Cmap::from_slice() reject inputs where this isn't true.
+    EXPECT_EQ(cmap.glyph_id_for_code_point(0xfeff), 0u);
+    EXPECT_EQ(cmap.glyph_id_for_code_point(0xffff), 0xffffu);
+    EXPECT_EQ(cmap.glyph_id_for_code_point(0x1'0000), 0u);
+}