Return Optional<FX_RECT> from GetBBox calls.

Change-Id: I5ebb56ff22613059b048dbe753f1970c28d6f8d4
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/81470
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_docpagedata.cpp b/core/fpdfapi/page/cpdf_docpagedata.cpp
index 47b5af2..70d4581 100644
--- a/core/fpdfapi/page/cpdf_docpagedata.cpp
+++ b/core/fpdfapi/page/cpdf_docpagedata.cpp
@@ -518,8 +518,7 @@
         });
   }
   int italicangle = pFont->GetSubstFontItalicAngle();
-  FX_RECT bbox;
-  pFont->GetBBox(&bbox);
+  FX_RECT bbox = pFont->GetBBox().value_or(FX_RECT());
   auto pBBox = pdfium::MakeRetain<CPDF_Array>();
   pBBox->AppendNew<CPDF_Number>(bbox.left);
   pBBox->AppendNew<CPDF_Number>(bbox.bottom);
diff --git a/core/fxge/cfx_font.cpp b/core/fxge/cfx_font.cpp
index 9c6d179..7d0f850 100644
--- a/core/fxge/cfx_font.cpp
+++ b/core/fxge/cfx_font.cpp
@@ -416,70 +416,72 @@
   return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face->GetRec()), descender);
 }
 
-bool CFX_Font::GetGlyphBBox(uint32_t glyph_index, FX_RECT* pBBox) {
+Optional<FX_RECT> CFX_Font::GetGlyphBBox(uint32_t glyph_index) {
   if (!m_Face)
-    return false;
+    return pdfium::nullopt;
 
+  FX_RECT result;
   if (FXFT_Is_Face_Tricky(m_Face->GetRec())) {
     int error = FT_Set_Char_Size(m_Face->GetRec(), 0, 1000 * 64, 72, 72);
     if (error)
-      return false;
+      return pdfium::nullopt;
 
     error = FT_Load_Glyph(m_Face->GetRec(), glyph_index,
                           FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
     if (error)
-      return false;
+      return pdfium::nullopt;
 
-    FT_BBox cbox;
     FT_Glyph glyph;
     error = FT_Get_Glyph(m_Face->GetRec()->glyph, &glyph);
     if (error)
-      return false;
+      return pdfium::nullopt;
 
+    FT_BBox cbox;
     FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &cbox);
     int pixel_size_x = m_Face->GetRec()->size->metrics.x_ppem;
     int pixel_size_y = m_Face->GetRec()->size->metrics.y_ppem;
     if (pixel_size_x == 0 || pixel_size_y == 0) {
-      pBBox->left = cbox.xMin;
-      pBBox->right = cbox.xMax;
-      pBBox->top = cbox.yMax;
-      pBBox->bottom = cbox.yMin;
+      result.left = cbox.xMin;
+      result.right = cbox.xMax;
+      result.top = cbox.yMax;
+      result.bottom = cbox.yMin;
     } else {
-      pBBox->left = cbox.xMin * 1000 / pixel_size_x;
-      pBBox->right = cbox.xMax * 1000 / pixel_size_x;
-      pBBox->top = cbox.yMax * 1000 / pixel_size_y;
-      pBBox->bottom = cbox.yMin * 1000 / pixel_size_y;
+      result.left = cbox.xMin * 1000 / pixel_size_x;
+      result.right = cbox.xMax * 1000 / pixel_size_x;
+      result.top = cbox.yMax * 1000 / pixel_size_y;
+      result.bottom = cbox.yMin * 1000 / pixel_size_y;
     }
-    pBBox->top = std::min(
-        pBBox->top,
+    result.top = std::min(
+        result.top,
         static_cast<int32_t>(FXFT_Get_Face_Ascender(m_Face->GetRec())));
-    pBBox->bottom = std::max(
-        pBBox->bottom,
+    result.bottom = std::max(
+        result.bottom,
         static_cast<int32_t>(FXFT_Get_Face_Descender(m_Face->GetRec())));
     FT_Done_Glyph(glyph);
-    return FT_Set_Pixel_Sizes(m_Face->GetRec(), 0, 64) == 0;
+    if (FT_Set_Pixel_Sizes(m_Face->GetRec(), 0, 64) != 0)
+      return pdfium::nullopt;
+    return result;
   }
-  if (FT_Load_Glyph(m_Face->GetRec(), glyph_index,
-                    FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
-    return false;
-  }
+  constexpr int kFlag = FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
+  if (FT_Load_Glyph(m_Face->GetRec(), glyph_index, kFlag) != 0)
+    return pdfium::nullopt;
   int em = FXFT_Get_Face_UnitsPerEM(m_Face->GetRec());
   if (em == 0) {
-    pBBox->left = FXFT_Get_Glyph_HoriBearingX(m_Face->GetRec());
-    pBBox->bottom = FXFT_Get_Glyph_HoriBearingY(m_Face->GetRec());
-    pBBox->top = pBBox->bottom - FXFT_Get_Glyph_Height(m_Face->GetRec());
-    pBBox->right = pBBox->left + FXFT_Get_Glyph_Width(m_Face->GetRec());
+    result.left = FXFT_Get_Glyph_HoriBearingX(m_Face->GetRec());
+    result.bottom = FXFT_Get_Glyph_HoriBearingY(m_Face->GetRec());
+    result.top = result.bottom - FXFT_Get_Glyph_Height(m_Face->GetRec());
+    result.right = result.left + FXFT_Get_Glyph_Width(m_Face->GetRec());
   } else {
-    pBBox->left = FXFT_Get_Glyph_HoriBearingX(m_Face->GetRec()) * 1000 / em;
-    pBBox->top = (FXFT_Get_Glyph_HoriBearingY(m_Face->GetRec()) -
+    result.left = FXFT_Get_Glyph_HoriBearingX(m_Face->GetRec()) * 1000 / em;
+    result.top = (FXFT_Get_Glyph_HoriBearingY(m_Face->GetRec()) -
                   FXFT_Get_Glyph_Height(m_Face->GetRec())) *
                  1000 / em;
-    pBBox->right = (FXFT_Get_Glyph_HoriBearingX(m_Face->GetRec()) +
+    result.right = (FXFT_Get_Glyph_HoriBearingX(m_Face->GetRec()) +
                     FXFT_Get_Glyph_Width(m_Face->GetRec())) *
                    1000 / em;
-    pBBox->bottom = (FXFT_Get_Glyph_HoriBearingY(m_Face->GetRec())) * 1000 / em;
+    result.bottom = (FXFT_Get_Glyph_HoriBearingY(m_Face->GetRec())) * 1000 / em;
   }
-  return true;
+  return result;
 }
 
 bool CFX_Font::IsItalic() const {
@@ -562,23 +564,22 @@
   return m_pSubstFont->m_Family;
 }
 
-bool CFX_Font::GetBBox(FX_RECT* pBBox) {
+Optional<FX_RECT> CFX_Font::GetBBox() {
   if (!m_Face)
-    return false;
+    return pdfium::nullopt;
 
+  FX_RECT result(FXFT_Get_Face_xMin(m_Face->GetRec()),
+                 FXFT_Get_Face_yMin(m_Face->GetRec()),
+                 FXFT_Get_Face_xMax(m_Face->GetRec()),
+                 FXFT_Get_Face_yMax(m_Face->GetRec()));
   int em = FXFT_Get_Face_UnitsPerEM(m_Face->GetRec());
-  if (em == 0) {
-    pBBox->left = FXFT_Get_Face_xMin(m_Face->GetRec());
-    pBBox->bottom = FXFT_Get_Face_yMax(m_Face->GetRec());
-    pBBox->top = FXFT_Get_Face_yMin(m_Face->GetRec());
-    pBBox->right = FXFT_Get_Face_xMax(m_Face->GetRec());
-  } else {
-    pBBox->left = FXFT_Get_Face_xMin(m_Face->GetRec()) * 1000 / em;
-    pBBox->top = FXFT_Get_Face_yMin(m_Face->GetRec()) * 1000 / em;
-    pBBox->right = FXFT_Get_Face_xMax(m_Face->GetRec()) * 1000 / em;
-    pBBox->bottom = FXFT_Get_Face_yMax(m_Face->GetRec()) * 1000 / em;
+  if (em != 0) {
+    result.left = (result.left * 1000) / em;
+    result.top = (result.top * 1000) / em;
+    result.right = (result.right * 1000) / em;
+    result.bottom = (result.bottom * 1000) / em;
   }
-  return true;
+  return result;
 }
 
 RetainPtr<CFX_GlyphCache> CFX_Font::GetOrCreateGlyphCache() const {
diff --git a/core/fxge/cfx_font.h b/core/fxge/cfx_font.h
index e25e394..e6d856a 100644
--- a/core/fxge/cfx_font.h
+++ b/core/fxge/cfx_font.h
@@ -17,6 +17,7 @@
 #include "core/fxcrt/retain_ptr.h"
 #include "core/fxge/cfx_face.h"
 #include "core/fxge/fx_freetype.h"
+#include "third_party/base/optional.h"
 #include "third_party/base/span.h"
 
 #if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
@@ -86,7 +87,7 @@
   int GetGlyphWidth(uint32_t glyph_index);
   int GetAscent() const;
   int GetDescent() const;
-  bool GetGlyphBBox(uint32_t glyph_index, FX_RECT* pBBox);
+  Optional<FX_RECT> GetGlyphBBox(uint32_t glyph_index);
   bool IsItalic() const;
   bool IsBold() const;
   bool IsFixedWidth() const;
@@ -99,7 +100,7 @@
   ByteString GetFaceName() const;
   ByteString GetBaseFontName(bool restrict_to_psname) const;
   bool IsTTFont() const;
-  bool GetBBox(FX_RECT* pBBox);
+  Optional<FX_RECT> GetBBox();
   bool IsEmbedded() const { return m_bEmbedded; }
   uint8_t* GetSubData() const { return m_pGsubData.get(); }
   void SetSubData(uint8_t* data) { m_pGsubData.reset(data); }
diff --git a/fpdfsdk/fpdf_edittext.cpp b/fpdfsdk/fpdf_edittext.cpp
index 7ac3e77..4c58e47 100644
--- a/fpdfsdk/fpdf_edittext.cpp
+++ b/fpdfsdk/fpdf_edittext.cpp
@@ -87,8 +87,7 @@
   flags |= FXFONT_NONSYMBOLIC;
 
   pFontDesc->SetNewFor<CPDF_Number>("Flags", flags);
-  FX_RECT bbox;
-  pFont->GetBBox(&bbox);
+  FX_RECT bbox = pFont->GetBBox().value_or(FX_RECT());
   pFontDesc->SetRectFor("FontBBox", CFX_FloatRect(bbox));
 
   // TODO(npm): calculate italic angle correctly
diff --git a/xfa/fgas/font/cfgas_gefont.cpp b/xfa/fgas/font/cfgas_gefont.cpp
index 39abd21..64bb174 100644
--- a/xfa/fgas/font/cfgas_gefont.cpp
+++ b/xfa/fgas/font/cfgas_gefont.cpp
@@ -182,33 +182,29 @@
   return *pWidth > 0;
 }
 
-bool CFGAS_GEFont::GetCharBBox(wchar_t wUnicode, FX_RECT* bbox) {
+Optional<FX_RECT> CFGAS_GEFont::GetCharBBox(wchar_t wUnicode) {
   auto it = m_BBoxMap.find(wUnicode);
-  if (it != m_BBoxMap.end()) {
-    *bbox = it->second;
-    return true;
-  }
+  if (it != m_BBoxMap.end())
+    return it->second;
 
   RetainPtr<CFGAS_GEFont> pFont;
   int32_t iGlyph;
   std::tie(iGlyph, pFont) = GetGlyphIndexAndFont(wUnicode, true);
   if (!pFont || iGlyph == 0xFFFF)
-    return false;
+    return pdfium::nullopt;
 
   if (pFont.Get() != this)
-    return pFont->GetCharBBox(wUnicode, bbox);
+    return pFont->GetCharBBox(wUnicode);
 
-  FX_RECT rtBBox;
-  if (!m_pFont->GetGlyphBBox(iGlyph, &rtBBox))
-    return false;
+  Optional<FX_RECT> rtBBox = m_pFont->GetGlyphBBox(iGlyph);
+  if (rtBBox.has_value())
+    m_BBoxMap[wUnicode] = rtBBox.value();
 
-  m_BBoxMap[wUnicode] = rtBBox;
-  *bbox = rtBBox;
-  return true;
+  return rtBBox;
 }
 
-bool CFGAS_GEFont::GetBBox(FX_RECT* bbox) {
-  return m_pFont->GetBBox(bbox);
+Optional<FX_RECT> CFGAS_GEFont::GetBBox() {
+  return m_pFont->GetBBox();
 }
 
 int32_t CFGAS_GEFont::GetGlyphIndex(wchar_t wUnicode) {
diff --git a/xfa/fgas/font/cfgas_gefont.h b/xfa/fgas/font/cfgas_gefont.h
index e9fbc7f..086f949 100644
--- a/xfa/fgas/font/cfgas_gefont.h
+++ b/xfa/fgas/font/cfgas_gefont.h
@@ -43,8 +43,8 @@
   int32_t GetAscent() const;
   int32_t GetDescent() const;
 
-  bool GetCharBBox(wchar_t wUnicode, FX_RECT* bbox);
-  bool GetBBox(FX_RECT* bbox);
+  Optional<FX_RECT> GetCharBBox(wchar_t wUnicode);
+  Optional<FX_RECT> GetBBox();
 
   RetainPtr<CFGAS_GEFont> GetSubstFont(int32_t iGlyphIndex);
   CFX_Font* GetDevFont() const { return m_pFont.Get(); }
diff --git a/xfa/fgas/layout/cfgas_txtbreak.cpp b/xfa/fgas/layout/cfgas_txtbreak.cpp
index 426e512..d1c3d48 100644
--- a/xfa/fgas/layout/cfgas_txtbreak.cpp
+++ b/xfa/fgas/layout/cfgas_txtbreak.cpp
@@ -863,16 +863,19 @@
         }
 
         if (chartype == FX_CHARTYPE::kCombination) {
-          FX_RECT rtBBox;
-          if (pFont->GetCharBBox(wForm, &rtBBox)) {
+          Optional<FX_RECT> rtBBox = pFont->GetCharBBox(wForm);
+          if (rtBBox.has_value()) {
             pCharPos->m_Origin.y =
-                fYBase + fFontSize - fFontSize * rtBBox.Height() / iMaxHeight;
+                fYBase + fFontSize -
+                fFontSize * rtBBox.value().Height() / iMaxHeight;
           }
           if (wForm == wch && wLast != 0xFEFF) {
             if (FX_GetCharType(wLast) == FX_CHARTYPE::kCombination) {
-              FX_RECT rtBox;
-              if (pFont->GetCharBBox(wLast, &rtBox))
-                pCharPos->m_Origin.y -= fFontSize * rtBox.Height() / iMaxHeight;
+              Optional<FX_RECT> rtOtherBox = pFont->GetCharBBox(wLast);
+              if (rtOtherBox.has_value()) {
+                pCharPos->m_Origin.y -=
+                    fFontSize * rtOtherBox.value().Height() / iMaxHeight;
+              }
             }
           }
         }