Use CIDToGIDMap to fill font widths in FPDFText_LoadCidType2Font()
FPDFText_LoadCidType2Font() generates a font dictionary that contains
various font characteristics. Use the caller-provided CIDToGIDMap to
fill the font widths array, instead of traversing the font's character
codes. This way, the widths array is only populated for the relevant
CIDs.
Bug: 376781381
Change-Id: Iae39b26bb18a8aa64f404570a8e557ef811a37ec
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/127950
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp
index cf5cb1b..fdec13a 100644
--- a/fpdfsdk/fpdf_edit_embeddertest.cpp
+++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -3802,7 +3802,7 @@
RetainPtr<const CPDF_Array> widths_array =
GetWidthsArrayForCidFont(typed_font);
ASSERT_TRUE(widths_array);
- CheckCompositeFontWidths(widths_array, typed_font, testing::Eq(9));
+ CheckCompositeFontWidths(widths_array, typed_font, testing::Eq(10));
FPDF_PAGEOBJECT text_object =
FPDFPageObj_CreateTextObj(document(), font.get(), 20.0f);
@@ -3869,9 +3869,7 @@
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));
+ CheckCompositeFontWidths(widths_array, typed_font, testing::Eq(5));
}
TEST_F(FPDFEditEmbedderTest, LoadCidType2FontWithBadParameters) {
diff --git a/fpdfsdk/fpdf_edittext.cpp b/fpdfsdk/fpdf_edittext.cpp
index 63ed5c2..17c81dd 100644
--- a/fpdfsdk/fpdf_edittext.cpp
+++ b/fpdfsdk/fpdf_edittext.cpp
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <algorithm>
+#include <limits>
#include <map>
#include <memory>
#include <sstream>
@@ -28,6 +29,7 @@
#include "core/fpdfapi/render/cpdf_renderstatus.h"
#include "core/fpdfapi/render/cpdf_textrenderer.h"
#include "core/fpdftext/cpdf_textpage.h"
+#include "core/fxcrt/byteorder.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/check_op.h"
#include "core/fxcrt/compiler_specific.h"
@@ -537,18 +539,14 @@
pdfium::span<const uint8_t> font_span,
const char* to_unicode_cmap,
pdfium::span<const uint8_t> cid_to_gid_map_span) {
+ CHECK_LE(cid_to_gid_map_span.size(), std::numeric_limits<uint32_t>::max());
+
// If it doesn't have a single char, just fail.
RetainPtr<CFX_Face> face = font->GetFace();
if (face->GetGlyphCount() <= 0) {
return nullptr;
}
- auto char_codes_and_indices =
- face->GetCharCodesAndIndices(pdfium::kMaximumSupplementaryCodePoint);
- if (char_codes_and_indices.empty()) {
- return nullptr;
- }
-
const ByteString name = BaseFontNameForType(font.get(), FPDF_FONT_TRUETYPE);
RetainPtr<CPDF_Dictionary> font_dict =
CreateCompositeFontDict(doc, font.get(), FPDF_FONT_TRUETYPE, name);
@@ -562,11 +560,13 @@
font_descriptor->GetObjNum());
std::map<uint32_t, uint32_t> widths;
- for (const auto& item : char_codes_and_indices) {
- if (!pdfium::Contains(widths, item.glyph_index)) {
- widths[item.glyph_index] = font->GetGlyphWidth(item.glyph_index);
- }
+ for (size_t i = 0; i < cid_to_gid_map_span.size(); i += 2) {
+ uint16_t glyph_index =
+ fxcrt::GetUInt16MSBFirst(cid_to_gid_map_span.subspan(i, 2));
+ // Safe to cast since `cid_to_gid_map_span` has a size limit.
+ widths[static_cast<uint32_t>(i) / 2] = font->GetGlyphWidth(glyph_index);
}
+
RetainPtr<CPDF_Array> widths_array = CreateWidthsArray(doc, widths);
cid_font_dict->SetNewFor<CPDF_Reference>("W", doc, widths_array->GetObjNum());