Encapsulate FT_Get_First_Char() and FT_Get_Next_Char()
Implement a method in CFX_Face to return all the char codes and glyph
indices, and change callers to use it.
Bug: pdfium:2037
Change-Id: Ib3d0ff0a17737f320467b8fab20eb590aa8ebd19
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/114795
Reviewed-by: Dominik Röttsches <drott@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxge/cfx_face.cpp b/core/fxge/cfx_face.cpp
index a5b5994..9bca779 100644
--- a/core/fxge/cfx_face.cpp
+++ b/core/fxge/cfx_face.cpp
@@ -8,6 +8,7 @@
#include <limits>
#include <memory>
#include <utility>
+#include <vector>
#include "core/fxge/cfx_font.h"
#include "core/fxge/cfx_fontmgr.h"
@@ -579,6 +580,26 @@
return FT_Get_Name_Index(GetRec(), name);
}
+std::vector<CFX_Face::CharCodeAndIndex> CFX_Face::GetCharCodesAndIndices(
+ char32_t max_char) {
+ CharCodeAndIndex char_code_and_index;
+ char_code_and_index.char_code = static_cast<uint32_t>(
+ FT_Get_First_Char(GetRec(), &char_code_and_index.glyph_index));
+ if (char_code_and_index.char_code > max_char) {
+ return {};
+ }
+ std::vector<CharCodeAndIndex> results = {char_code_and_index};
+ while (true) {
+ char_code_and_index.char_code = static_cast<uint32_t>(FT_Get_Next_Char(
+ GetRec(), results.back().char_code, &char_code_and_index.glyph_index));
+ if (char_code_and_index.char_code > max_char ||
+ char_code_and_index.glyph_index == 0) {
+ return results;
+ }
+ results.push_back(char_code_and_index);
+ }
+}
+
CFX_Face::CharMap CFX_Face::GetCurrentCharMap() const {
return GetRec()->charmap;
}
diff --git a/core/fxge/cfx_face.h b/core/fxge/cfx_face.h
index 6c57504..551f358 100644
--- a/core/fxge/cfx_face.h
+++ b/core/fxge/cfx_face.h
@@ -9,6 +9,7 @@
#include <array>
#include <memory>
+#include <vector>
#include "build/build_config.h"
#include "core/fxcrt/bytestring.h"
@@ -32,6 +33,11 @@
public:
using CharMap = void*;
+ struct CharCodeAndIndex {
+ uint32_t char_code;
+ uint32_t glyph_index;
+ };
+
static RetainPtr<CFX_Face> New(FT_Library library,
RetainPtr<Retainable> pDesc,
pdfium::span<const FT_Byte> data,
@@ -95,6 +101,8 @@
int GetCharIndex(uint32_t code);
int GetNameIndex(const char* name);
+ std::vector<CharCodeAndIndex> GetCharCodesAndIndices(char32_t max_char);
+
CharMap GetCurrentCharMap() const;
absl::optional<fxge::FontEncoding> GetCurrentCharMapEncoding() const;
int GetCharMapPlatformIdByIndex(size_t index) const;
diff --git a/fpdfsdk/fpdf_edittext.cpp b/fpdfsdk/fpdf_edittext.cpp
index 73e9916..608a4db 100644
--- a/fpdfsdk/fpdf_edittext.cpp
+++ b/fpdfsdk/fpdf_edittext.cpp
@@ -310,31 +310,31 @@
return nullptr;
}
- uint32_t dwGlyphIndex;
- uint32_t dwCurrentChar = static_cast<uint32_t>(
- FT_Get_First_Char(pFont->GetFaceRec(), &dwGlyphIndex));
+ // Simple fonts have 1-byte charcodes only.
static constexpr uint32_t kMaxSimpleFontChar = 0xFF;
- if (dwCurrentChar > kMaxSimpleFontChar) {
+ auto char_codes_and_indices =
+ pFont->GetFace()->GetCharCodesAndIndices(kMaxSimpleFontChar);
+ if (char_codes_and_indices.empty()) {
return nullptr;
}
- pFontDict->SetNewFor<CPDF_Number>("FirstChar",
- static_cast<int>(dwCurrentChar));
- auto widthsArray = pDoc->NewIndirect<CPDF_Array>();
- while (true) {
- widthsArray->AppendNew<CPDF_Number>(pFont->GetGlyphWidth(dwGlyphIndex));
- uint32_t nextChar = static_cast<uint32_t>(
- FT_Get_Next_Char(pFont->GetFaceRec(), dwCurrentChar, &dwGlyphIndex));
- // Simple fonts have 1-byte charcodes only.
- if (nextChar > kMaxSimpleFontChar || dwGlyphIndex == 0)
- break;
- for (uint32_t i = dwCurrentChar + 1; i < nextChar; i++)
- widthsArray->AppendNew<CPDF_Number>(0);
- dwCurrentChar = nextChar;
+
+ pFontDict->SetNewFor<CPDF_Number>(
+ "FirstChar", static_cast<int>(char_codes_and_indices[0].char_code));
+ auto widths_array = pDoc->NewIndirect<CPDF_Array>();
+ for (size_t i = 0; i < char_codes_and_indices.size(); ++i) {
+ widths_array->AppendNew<CPDF_Number>(
+ pFont->GetGlyphWidth(char_codes_and_indices[i].glyph_index));
+ if (i > 0 && i < char_codes_and_indices.size() - 1) {
+ for (uint32_t j = char_codes_and_indices[i - 1].char_code + 1;
+ j < char_codes_and_indices[i].char_code; ++j) {
+ widths_array->AppendNew<CPDF_Number>(0);
+ }
+ }
}
- pFontDict->SetNewFor<CPDF_Number>("LastChar",
- static_cast<int>(dwCurrentChar));
+ pFontDict->SetNewFor<CPDF_Number>(
+ "LastChar", static_cast<int>(char_codes_and_indices.back().char_code));
pFontDict->SetNewFor<CPDF_Reference>("Widths", pDoc,
- widthsArray->GetObjNum());
+ widths_array->GetObjNum());
RetainPtr<CPDF_Dictionary> pFontDesc =
LoadFontDesc(pDoc, name, pFont.get(), span, font_type);
@@ -383,27 +383,19 @@
return nullptr;
}
- uint32_t dwGlyphIndex;
- uint32_t dwCurrentChar = static_cast<uint32_t>(
- FT_Get_First_Char(pFont->GetFaceRec(), &dwGlyphIndex));
- if (dwCurrentChar > pdfium::kMaximumSupplementaryCodePoint) {
+ auto char_codes_and_indices = pFont->GetFace()->GetCharCodesAndIndices(
+ pdfium::kMaximumSupplementaryCodePoint);
+ if (char_codes_and_indices.empty()) {
return nullptr;
}
std::multimap<uint32_t, uint32_t> to_unicode;
std::map<uint32_t, uint32_t> widths;
- while (true) {
- if (dwCurrentChar > pdfium::kMaximumSupplementaryCodePoint) {
- break;
+ for (const auto& item : char_codes_and_indices) {
+ if (!pdfium::Contains(widths, item.glyph_index)) {
+ widths[item.glyph_index] = pFont->GetGlyphWidth(item.glyph_index);
}
-
- if (!pdfium::Contains(widths, dwGlyphIndex))
- widths[dwGlyphIndex] = pFont->GetGlyphWidth(dwGlyphIndex);
- to_unicode.emplace(dwGlyphIndex, dwCurrentChar);
- dwCurrentChar = static_cast<uint32_t>(
- FT_Get_Next_Char(pFont->GetFaceRec(), dwCurrentChar, &dwGlyphIndex));
- if (dwGlyphIndex == 0)
- break;
+ to_unicode.emplace(item.glyph_index, item.char_code);
}
auto widthsArray = pDoc->NewIndirect<CPDF_Array>();
for (auto it = widths.begin(); it != widths.end(); ++it) {