Check the font width array generated by FPDFText_LoadCidType2Font()
Add a test case to show FPDFText_LoadCidType2Font() generates a font
widths array with more entries than strictly necessary, when the CID to
GID mapping contains only a few entries.
Augment the existing CheckCompositeFontWidths() helper to be able to
count the exact number of expected CIDs, if desired.
Bug: 376781381
Change-Id: I76ef3dbf2a920f701443caa4cc8b0538939c2a97
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/128011
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp
index 799a7e1..cf5cb1b 100644
--- a/fpdfsdk/fpdf_edit_embeddertest.cpp
+++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -26,6 +26,7 @@
#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxcrt/span_util.h"
+#include "core/fxcrt/stl_util.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
#include "core/fxge/fx_font.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
@@ -249,7 +250,8 @@
}
void CheckCompositeFontWidths(const CPDF_Array* widths_array,
- CPDF_Font* typed_font) {
+ CPDF_Font* typed_font,
+ testing::Matcher<int> matcher) {
// Check that W array is in a format that conforms to PDF spec 1.7 section
// "Glyph Metrics in CIDFonts" (these checks are not
// implementation-specific).
@@ -285,9 +287,10 @@
}
num_cids_checked += last_cid - cid + 1;
}
- // Make sure we have a good amount of cids described
- EXPECT_GT(num_cids_checked, 200);
+ // Check the CID count.
+ EXPECT_THAT(num_cids_checked, matcher);
}
+
CPDF_Document* cpdf_doc() { return cpdf_doc_; }
private:
@@ -3557,7 +3560,7 @@
RetainPtr<const CPDF_Array> widths_array = cidfont_dict->GetArrayFor("W");
ASSERT_TRUE(widths_array);
EXPECT_GT(widths_array->size(), 1u);
- CheckCompositeFontWidths(widths_array.Get(), typed_font);
+ CheckCompositeFontWidths(widths_array, typed_font, testing::Ge(201));
}
TEST_F(FPDFEditEmbedderTest, LoadCIDType2Font) {
@@ -3600,7 +3603,7 @@
// Check widths
RetainPtr<const CPDF_Array> widths_array = cidfont_dict->GetArrayFor("W");
ASSERT_TRUE(widths_array);
- CheckCompositeFontWidths(widths_array.Get(), typed_font);
+ CheckCompositeFontWidths(widths_array, typed_font, testing::Ge(201));
}
TEST_F(FPDFEditEmbedderTest, NormalizeNegativeRotation) {
@@ -3788,13 +3791,18 @@
end
)";
- const std::vector<uint8_t> cid_to_gid_map = {0, 0, 0, 1, 0, 2, 0, 3, 0, 4,
- 0, 5, 0, 6, 0, 7, 0, 8, 0, 9};
+ static constexpr auto kCidToGidMap = fxcrt::ToArray<const uint8_t>(
+ {0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9});
ScopedFPDFFont font(FPDFText_LoadCidType2Font(
document(), font_data.data(), font_data.size(), kToUnicodeCMap,
- cid_to_gid_map.data(), cid_to_gid_map.size()));
+ kCidToGidMap.data(), kCidToGidMap.size()));
ASSERT_TRUE(font);
+ CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
+ RetainPtr<const CPDF_Array> widths_array =
+ GetWidthsArrayForCidFont(typed_font);
+ ASSERT_TRUE(widths_array);
+ CheckCompositeFontWidths(widths_array, typed_font, testing::Eq(9));
FPDF_PAGEOBJECT text_object =
FPDFPageObj_CreateTextObj(document(), font.get(), 20.0f);
@@ -3816,6 +3824,56 @@
VerifySavedDocument(400, 400, NotoSansSCChecksum());
}
+TEST_F(FPDFEditEmbedderTest, LoadCidType2FontCustomGeneratedWidths) {
+ CreateEmptyDocument();
+ std::string font_path;
+ ASSERT_TRUE(PathService::GetThirdPartyFilePath(
+ "NotoSansCJK/NotoSansSC-Regular.subset.otf", &font_path));
+
+ std::vector<uint8_t> font_data = GetFileContents(font_path.c_str());
+ ASSERT_FALSE(font_data.empty());
+
+ static const char kToUnicodeCMap[] = R"(
+/CIDInit /ProcSet findresource begin
+12 dict begin
+begincmap
+/CIDSystemInfo <<
+ /Registry (Adobe)
+ /Ordering (Identity)
+ /Supplement 0
+>> def
+/CMapName /Adobe-Identity-H def
+/CMapType 2 def
+1 begincodespacerange
+<0000> <FFFF>
+endcodespacerange
+3 beginbfrange
+<0002> <0003> [<3002> <2F00>]
+<0003> <0004> [<4E00> <2F06>]
+<0004> <0005> [<4E8C> <53E5>]
+endbfrange
+endcmap
+CMapName currentdict /CMap defineresource pop
+end
+end
+)";
+
+ static constexpr auto kCidToGidMap =
+ fxcrt::ToArray<const uint8_t>({0, 0, 0, 1, 0, 2, 0, 3, 0, 4});
+
+ ScopedFPDFFont font(FPDFText_LoadCidType2Font(
+ document(), font_data.data(), font_data.size(), kToUnicodeCMap,
+ kCidToGidMap.data(), kCidToGidMap.size()));
+ ASSERT_TRUE(font);
+ CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
+ RetainPtr<const CPDF_Array> widths_array =
+ GetWidthsArrayForCidFont(typed_font);
+ ASSERT_TRUE(widths_array);
+ // TODO(crbug.com/376781381): Reduce `widths_array` size, given the smaller
+ // `kCidToGidMap`.
+ CheckCompositeFontWidths(widths_array, typed_font, testing::Eq(9));
+}
+
TEST_F(FPDFEditEmbedderTest, LoadCidType2FontWithBadParameters) {
ASSERT_TRUE(CreateNewDocument());