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());