summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNico Weber <thakis@chromium.org>2022-04-03 11:26:36 -0400
committerAndreas Kling <kling@serenityos.org>2022-04-03 19:16:03 +0200
commitfd821213191f78a897dcacef40e8658737e9526e (patch)
tree34a927527db0258f322e8adcc87c36831e6528a6
parent9b2460077951bcdd3137f82c961bd8fc4645c2fc (diff)
downloadserenity-fd821213191f78a897dcacef40e8658737e9526e.zip
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.
-rw-r--r--Meta/Lagom/CMakeLists.txt8
-rw-r--r--Tests/LibTTF/CMakeLists.txt7
-rw-r--r--Tests/LibTTF/TestCmap.cpp81
3 files changed, 95 insertions, 1 deletions
diff --git a/Meta/Lagom/CMakeLists.txt b/Meta/Lagom/CMakeLists.txt
index bd4403889c..4752ec9e96 100644
--- a/Meta/Lagom/CMakeLists.txt
+++ b/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})
diff --git a/Tests/LibTTF/CMakeLists.txt b/Tests/LibTTF/CMakeLists.txt
new file mode 100644
index 0000000000..15bdb527ab
--- /dev/null
+++ b/Tests/LibTTF/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(TEST_SOURCES
+ TestCmap.cpp
+)
+
+foreach(source IN LISTS TEST_SOURCES)
+ serenity_test("${source}" LibGfx)
+endforeach()
diff --git a/Tests/LibTTF/TestCmap.cpp b/Tests/LibTTF/TestCmap.cpp
new file mode 100644
index 0000000000..f69829d387
--- /dev/null
+++ b/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);
+}