Improve CPDF_CMapParser::HandleCid() performance

Send the entire range of codes to write to CPDF_CMap in one go. Then
CPDF_CMap can create a single span and write all the values, instead of
creating one span per value. While spans are not expensive to create,
creating 64K spans in a loop does add up. This makes pdf_cmap_fuzzer run
3X as fast for the problematic input.

Bug: chromium:1478569
Change-Id: I3322de8aeaff23c5e562d4acc55ade57c0cc03ad
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/111730
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/font/cpdf_cmap.cpp b/core/fpdfapi/font/cpdf_cmap.cpp
index d5fa61b..a38eab4 100644
--- a/core/fpdfapi/font/cpdf_cmap.cpp
+++ b/core/fpdfapi/font/cpdf_cmap.cpp
@@ -515,3 +515,12 @@
 void CPDF_CMap::SetMixedFourByteLeadingRanges(std::vector<CodeRange> ranges) {
   m_MixedFourByteLeadingRanges = std::move(ranges);
 }
+
+void CPDF_CMap::SetDirectCharcodeToCIDTableRange(uint32_t start_code,
+                                                 uint32_t end_code,
+                                                 uint16_t start_cid) {
+  pdfium::span<uint16_t> span = m_DirectCharcodeToCIDTable.writable_span();
+  for (uint32_t code = start_code; code <= end_code; ++code) {
+    span[code] = static_cast<uint16_t>(start_cid + code - start_code);
+  }
+}
diff --git a/core/fpdfapi/font/cpdf_cmap.h b/core/fpdfapi/font/cpdf_cmap.h
index 416010a..5469979 100644
--- a/core/fpdfapi/font/cpdf_cmap.h
+++ b/core/fpdfapi/font/cpdf_cmap.h
@@ -77,9 +77,9 @@
   CIDSet GetCharset() const { return m_Charset; }
   void SetCharset(CIDSet set) { m_Charset = set; }
 
-  void SetDirectCharcodeToCIDTable(size_t idx, uint16_t val) {
-    m_DirectCharcodeToCIDTable.writable_span()[idx] = val;
-  }
+  void SetDirectCharcodeToCIDTableRange(uint32_t start_code,
+                                        uint32_t end_code,
+                                        uint16_t start_cid);
   bool IsDirectCharcodeToCIDTableIsEmpty() const {
     return m_DirectCharcodeToCIDTable.empty();
   }
diff --git a/core/fpdfapi/font/cpdf_cmapparser.cpp b/core/fpdfapi/font/cpdf_cmapparser.cpp
index 87a5907..465b6fc 100644
--- a/core/fpdfapi/font/cpdf_cmapparser.cpp
+++ b/core/fpdfapi/font/cpdf_cmapparser.cpp
@@ -100,10 +100,7 @@
     StartCID = static_cast<uint16_t>(m_CodePoints[2]);
   }
   if (EndCode < CPDF_CMap::kDirectMapTableSize) {
-    for (uint32_t code = StartCode; code <= EndCode; code++) {
-      m_pCMap->SetDirectCharcodeToCIDTable(
-          code, static_cast<uint16_t>(StartCID + code - StartCode));
-    }
+    m_pCMap->SetDirectCharcodeToCIDTableRange(StartCode, EndCode, StartCID);
   } else {
     m_AdditionalCharcodeToCIDMappings.push_back({StartCode, EndCode, StartCID});
   }