Use floats in experimental APIs.

Floats work more seamlessly with the underlying implementation, which
uses floats instead of doubles. Along the way, take advantage of
FS_MATRIX to reduce the number of parameters in these APIs. Also
introduce FS_POINTF for the same purpose.

NOTE: This breaks API compatibility.

The modified APIS are:
- FPDFAnnot_GetFormFieldAtPoint
- FPDFFormObj_GetMatrix
- FPDFPath_GetMatrix
- FPDFPath_SetMatrix
- FPDFText_GetCharAngle
- FPDFText_GetLooseCharBox
- FPDFTextObj_GetFontSize
- FPDFTextObj_GetMatrix

Bug: pdfium:996
Change-Id: I58d43928811cf019fef3017ebce670322720db4d
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/61873
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/fpdfsdk/cpdfsdk_helpers.cpp b/fpdfsdk/cpdfsdk_helpers.cpp
index f03f2b1..526b262 100644
--- a/fpdfsdk/cpdfsdk_helpers.cpp
+++ b/fpdfsdk/cpdfsdk_helpers.cpp
@@ -247,11 +247,15 @@
   return true;
 }
 
-CFX_FloatRect CFXFloatRectFromFSRECTF(const FS_RECTF& rect) {
+CFX_PointF CFXPointFFromFSPointF(const FS_POINTF& point) {
+  return CFX_PointF(point.x, point.y);
+}
+
+CFX_FloatRect CFXFloatRectFromFSRectF(const FS_RECTF& rect) {
   return CFX_FloatRect(rect.left, rect.bottom, rect.right, rect.top);
 }
 
-FS_RECTF FSRECTFFromCFXFloatRect(const CFX_FloatRect& rect) {
+FS_RECTF FSRectFFromCFXFloatRect(const CFX_FloatRect& rect) {
   return {rect.left, rect.top, rect.right, rect.bottom};
 }
 
@@ -259,6 +263,15 @@
   return CFX_Matrix(matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f);
 }
 
+void FSMatrixFromCFXMatrix(const CFX_Matrix& matrix, FS_MATRIX* out_matrix) {
+  out_matrix->a = matrix.a;
+  out_matrix->b = matrix.b;
+  out_matrix->c = matrix.c;
+  out_matrix->d = matrix.d;
+  out_matrix->e = matrix.e;
+  out_matrix->f = matrix.f;
+}
+
 unsigned long Utf16EncodeMaybeCopyAndReturnLength(const WideString& text,
                                                   void* buffer,
                                                   unsigned long buflen) {
diff --git a/fpdfsdk/cpdfsdk_helpers.h b/fpdfsdk/cpdfsdk_helpers.h
index 4b84395..6ba7fe1 100644
--- a/fpdfsdk/cpdfsdk_helpers.h
+++ b/fpdfsdk/cpdfsdk_helpers.h
@@ -232,10 +232,13 @@
                           size_t quad_index,
                           FS_QUADPOINTSF* quad_points);
 
-CFX_FloatRect CFXFloatRectFromFSRECTF(const FS_RECTF& rect);
-FS_RECTF FSRECTFFromCFXFloatRect(const CFX_FloatRect& rect);
+CFX_PointF CFXPointFFromFSPointF(const FS_POINTF& point);
+
+CFX_FloatRect CFXFloatRectFromFSRectF(const FS_RECTF& rect);
+FS_RECTF FSRectFFromCFXFloatRect(const CFX_FloatRect& rect);
 
 CFX_Matrix CFXMatrixFromFSMatrix(const FS_MATRIX& matrix);
+void FSMatrixFromCFXMatrix(const CFX_Matrix& matrix, FS_MATRIX* out_matrix);
 
 unsigned long Utf16EncodeMaybeCopyAndReturnLength(const WideString& text,
                                                   void* buffer,
diff --git a/fpdfsdk/fpdf_annot.cpp b/fpdfsdk/fpdf_annot.cpp
index 46c0106..d77cee6 100644
--- a/fpdfsdk/fpdf_annot.cpp
+++ b/fpdfsdk/fpdf_annot.cpp
@@ -656,7 +656,7 @@
   if (!pAnnotDict || !rect)
     return false;
 
-  CFX_FloatRect newRect = CFXFloatRectFromFSRECTF(*rect);
+  CFX_FloatRect newRect = CFXFloatRectFromFSRectF(*rect);
 
   // Update the "Rect" entry in the annotation dictionary.
   pAnnotDict->SetRectFor(pdfium::annotation::kRect, newRect);
@@ -682,7 +682,7 @@
   if (!pAnnotDict || !rect)
     return false;
 
-  *rect = FSRECTFFromCFXFloatRect(
+  *rect = FSRectFFromCFXFloatRect(
       pAnnotDict->GetRectFor(pdfium::annotation::kRect));
   return true;
 }
@@ -884,8 +884,10 @@
 FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV
 FPDFAnnot_GetFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
                               FPDF_PAGE page,
-                              double page_x,
-                              double page_y) {
+                              const FS_POINTF* point) {
+  if (!point)
+    return nullptr;
+
   CPDFSDK_InteractiveForm* pForm = FormHandleToInteractiveForm(hHandle);
   if (!pForm)
     return nullptr;
@@ -897,8 +899,7 @@
   CPDF_InteractiveForm* pPDFForm = pForm->GetInteractiveForm();
   int annot_index = -1;
   CPDF_FormControl* pFormCtrl = pPDFForm->GetControlAtPoint(
-      pPage, CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)),
-      &annot_index);
+      pPage, CFXPointFFromFSPointF(*point), &annot_index);
   if (!pFormCtrl || annot_index == -1)
     return nullptr;
   return FPDFPage_GetAnnot(page, annot_index);
diff --git a/fpdfsdk/fpdf_annot_embeddertest.cpp b/fpdfsdk/fpdf_annot_embeddertest.cpp
index 967f488..1af2a0d 100644
--- a/fpdfsdk/fpdf_annot_embeddertest.cpp
+++ b/fpdfsdk/fpdf_annot_embeddertest.cpp
@@ -1547,19 +1547,23 @@
   ASSERT_TRUE(page);
 
   // Attempt to get an annotation where no annotation exists on page.
-  EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 0, 0));
+  static const FS_POINTF kOriginPoint = {0.0f, 0.0f};
+  EXPECT_FALSE(
+      FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kOriginPoint));
 
+  static const FS_POINTF kValidPoint = {120.0f, 120.0f};
   {
     // Verify there is an annotation.
     ScopedFPDFAnnotation annot(
-        FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 120, 120));
+        FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kValidPoint));
     EXPECT_TRUE(annot);
   }
 
   // Try other bad inputs at a valid location.
-  EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(nullptr, nullptr, 120, 120));
-  EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(nullptr, page, 120, 120));
-  EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(form_handle(), nullptr, 120, 120));
+  EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(nullptr, nullptr, &kValidPoint));
+  EXPECT_FALSE(FPDFAnnot_GetFormFieldAtPoint(nullptr, page, &kValidPoint));
+  EXPECT_FALSE(
+      FPDFAnnot_GetFormFieldAtPoint(form_handle(), nullptr, &kValidPoint));
 
   UnloadPage(page);
 }
@@ -1572,8 +1576,9 @@
 
   {
     // Retrieve user-editable text field annotation.
+    static const FS_POINTF kPoint = {105.0f, 118.0f};
     ScopedFPDFAnnotation annot(
-        FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 105, 118));
+        FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
     ASSERT_TRUE(annot);
 
     // Check that interactive form annotation flag values are as expected.
@@ -1583,8 +1588,9 @@
 
   {
     // Retrieve read-only text field annotation.
+    static const FS_POINTF kPoint = {105.0f, 202.0f};
     ScopedFPDFAnnotation annot(
-        FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 105, 202));
+        FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
     ASSERT_TRUE(annot);
 
     // Check that interactive form annotation flag values are as expected.
@@ -1603,8 +1609,9 @@
 
   {
     // Retrieve user-editable combobox annotation.
+    static const FS_POINTF kPoint = {102.0f, 363.0f};
     ScopedFPDFAnnotation annot(
-        FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 102, 363));
+        FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
     ASSERT_TRUE(annot);
 
     // Check that interactive form annotation flag values are as expected.
@@ -1616,8 +1623,9 @@
 
   {
     // Retrieve regular combobox annotation.
+    static const FS_POINTF kPoint = {102.0f, 413.0f};
     ScopedFPDFAnnotation annot(
-        FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 102, 413));
+        FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
     ASSERT_TRUE(annot);
 
     // Check that interactive form annotation flag values are as expected.
@@ -1629,8 +1637,9 @@
 
   {
     // Retrieve read-only combobox annotation.
+    static const FS_POINTF kPoint = {102.0f, 513.0f};
     ScopedFPDFAnnotation annot(
-        FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 102, 513));
+        FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, &kPoint));
     ASSERT_TRUE(annot);
 
     // Check that interactive form annotation flag values are as expected.
diff --git a/fpdfsdk/fpdf_doc.cpp b/fpdfsdk/fpdf_doc.cpp
index b789891..ec361d5 100644
--- a/fpdfsdk/fpdf_doc.cpp
+++ b/fpdfsdk/fpdf_doc.cpp
@@ -367,7 +367,7 @@
     return false;
 
   CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFLink(link_annot);
-  *rect = FSRECTFFromCFXFloatRect(pAnnotDict->GetRectFor("Rect"));
+  *rect = FSRectFFromCFXFloatRect(pAnnotDict->GetRectFor("Rect"));
   return true;
 }
 
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp
index f743406..0c5167b 100644
--- a/fpdfsdk/fpdf_edit_embeddertest.cpp
+++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -263,43 +263,23 @@
   EXPECT_EQ(FPDF_FILLMODE_ALTERNATE, fillmode);
   EXPECT_FALSE(stroke);
 
-  double matrix_a = 1;
-  double matrix_b = 2;
-  double matrix_c = 3;
-  double matrix_d = 4;
-  double matrix_e = 5;
-  double matrix_f = 6;
-  EXPECT_FALSE(FPDFPath_SetMatrix(nullptr, matrix_a, matrix_b, matrix_c,
-                                  matrix_d, matrix_e, matrix_f));
-  EXPECT_TRUE(FPDFPath_SetMatrix(red_rect, matrix_a, matrix_b, matrix_c,
-                                 matrix_d, matrix_e, matrix_f));
-  // Set to 0 before FPDFPath_GetMatrix() to ensure they are actually set by
-  // the function.
-  matrix_a = 0;
-  matrix_b = 0;
-  matrix_c = 0;
-  matrix_d = 0;
-  matrix_e = 0;
-  matrix_f = 0;
-  EXPECT_FALSE(FPDFPath_GetMatrix(nullptr, &matrix_a, &matrix_b, &matrix_c,
-                                  &matrix_d, &matrix_e, &matrix_f));
-  EXPECT_TRUE(FPDFPath_GetMatrix(red_rect, &matrix_a, &matrix_b, &matrix_c,
-                                 &matrix_d, &matrix_e, &matrix_f));
-  EXPECT_EQ(1, static_cast<int>(matrix_a));
-  EXPECT_EQ(2, static_cast<int>(matrix_b));
-  EXPECT_EQ(3, static_cast<int>(matrix_c));
-  EXPECT_EQ(4, static_cast<int>(matrix_d));
-  EXPECT_EQ(5, static_cast<int>(matrix_e));
-  EXPECT_EQ(6, static_cast<int>(matrix_f));
-  // Set back the default
-  matrix_a = 1;
-  matrix_b = 0;
-  matrix_c = 0;
-  matrix_d = 1;
-  matrix_e = 0;
-  matrix_f = 0;
-  EXPECT_TRUE(FPDFPath_SetMatrix(red_rect, matrix_a, matrix_b, matrix_c,
-                                 matrix_d, matrix_e, matrix_f));
+  static const FS_MATRIX kMatrix = {1, 2, 3, 4, 5, 6};
+  EXPECT_FALSE(FPDFPath_SetMatrix(nullptr, &kMatrix));
+  EXPECT_TRUE(FPDFPath_SetMatrix(red_rect, &kMatrix));
+
+  FS_MATRIX matrix;
+  EXPECT_FALSE(FPDFPath_GetMatrix(nullptr, &matrix));
+  EXPECT_TRUE(FPDFPath_GetMatrix(red_rect, &matrix));
+  EXPECT_FLOAT_EQ(1.0f, matrix.a);
+  EXPECT_FLOAT_EQ(2.0f, matrix.b);
+  EXPECT_FLOAT_EQ(3.0f, matrix.c);
+  EXPECT_FLOAT_EQ(4.0f, matrix.d);
+  EXPECT_FLOAT_EQ(5.0f, matrix.e);
+  EXPECT_FLOAT_EQ(6.0f, matrix.f);
+
+  // Set back the identity matrix.
+  matrix = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
+  EXPECT_TRUE(FPDFPath_SetMatrix(red_rect, &matrix));
 
   FPDFPage_InsertObject(page, red_rect);
   {
@@ -2072,23 +2052,15 @@
     VerifySavedDocument(612, 792, md5);
   }
 
-  double matrix_a = 0;
-  double matrix_b = 0;
-  double matrix_c = 0;
-  double matrix_d = 0;
-  double matrix_e = 0;
-  double matrix_f = 0;
-  EXPECT_FALSE(FPDFTextObj_GetMatrix(nullptr, &matrix_a, &matrix_b, &matrix_c,
-                                     &matrix_d, &matrix_e, &matrix_f));
-  EXPECT_TRUE(FPDFTextObj_GetMatrix(text_object3, &matrix_a, &matrix_b,
-                                    &matrix_c, &matrix_d, &matrix_e,
-                                    &matrix_f));
-  EXPECT_EQ(1., matrix_a);
-  EXPECT_EQ(1.5, matrix_b);
-  EXPECT_EQ(2., matrix_c);
-  EXPECT_EQ(0.5, matrix_d);
-  EXPECT_EQ(200., matrix_e);
-  EXPECT_EQ(200., matrix_f);
+  FS_MATRIX matrix;
+  EXPECT_FALSE(FPDFTextObj_GetMatrix(nullptr, &matrix));
+  EXPECT_TRUE(FPDFTextObj_GetMatrix(text_object3, &matrix));
+  EXPECT_FLOAT_EQ(1.0f, matrix.a);
+  EXPECT_FLOAT_EQ(1.5f, matrix.b);
+  EXPECT_FLOAT_EQ(2.0f, matrix.c);
+  EXPECT_FLOAT_EQ(0.5f, matrix.d);
+  EXPECT_FLOAT_EQ(200.0f, matrix.e);
+  EXPECT_FLOAT_EQ(200.0f, matrix.f);
 
   EXPECT_EQ(0, FPDFTextObj_GetFontSize(nullptr));
   EXPECT_EQ(20, FPDFTextObj_GetFontSize(text_object3));
@@ -2180,32 +2152,22 @@
   pFormObj->Transform(pFormObj->form_matrix().GetInverse());
 
   // FPDFFormObj_GetMatrix() positive testing.
-  static constexpr float kFloats[6] = {1.0, 1.5, 2.0, 2.5, 100.0, 200.0};
-  CFX_Matrix matrix(kFloats);
-  pFormObj->Transform(matrix);
+  static constexpr FS_MATRIX kMatrix = {1.0f, 1.5f, 2.0f, 2.5f, 100.0f, 200.0f};
+  pFormObj->Transform(CFXMatrixFromFSMatrix(kMatrix));
 
-  double matrix_a = 0;
-  double matrix_b = 0;
-  double matrix_c = 0;
-  double matrix_d = 0;
-  double matrix_e = 0;
-  double matrix_f = 0;
-  EXPECT_TRUE(FPDFFormObj_GetMatrix(form, &matrix_a, &matrix_b, &matrix_c,
-                                    &matrix_d, &matrix_e, &matrix_f));
-  EXPECT_DOUBLE_EQ(kFloats[0], matrix_a);
-  EXPECT_DOUBLE_EQ(kFloats[1], matrix_b);
-  EXPECT_DOUBLE_EQ(kFloats[2], matrix_c);
-  EXPECT_DOUBLE_EQ(kFloats[3], matrix_d);
-  EXPECT_DOUBLE_EQ(kFloats[4], matrix_e);
-  EXPECT_DOUBLE_EQ(kFloats[5], matrix_f);
+  FS_MATRIX matrix;
+  EXPECT_TRUE(FPDFFormObj_GetMatrix(form, &matrix));
+  EXPECT_FLOAT_EQ(kMatrix.a, matrix.a);
+  EXPECT_FLOAT_EQ(kMatrix.b, matrix.b);
+  EXPECT_FLOAT_EQ(kMatrix.c, matrix.c);
+  EXPECT_FLOAT_EQ(kMatrix.d, matrix.d);
+  EXPECT_FLOAT_EQ(kMatrix.e, matrix.e);
+  EXPECT_FLOAT_EQ(kMatrix.f, matrix.f);
 
   // FPDFFormObj_GetMatrix() negative testing.
-  EXPECT_FALSE(FPDFFormObj_GetMatrix(nullptr, &matrix_a, &matrix_b, &matrix_c,
-                                     &matrix_d, &matrix_e, &matrix_f));
-  EXPECT_FALSE(FPDFFormObj_GetMatrix(form, nullptr, nullptr, nullptr, nullptr,
-                                     nullptr, nullptr));
-  EXPECT_FALSE(FPDFFormObj_GetMatrix(nullptr, nullptr, nullptr, nullptr,
-                                     nullptr, nullptr, nullptr));
+  EXPECT_FALSE(FPDFFormObj_GetMatrix(nullptr, &matrix));
+  EXPECT_FALSE(FPDFFormObj_GetMatrix(form, nullptr));
+  EXPECT_FALSE(FPDFFormObj_GetMatrix(nullptr, nullptr));
 
   UnloadPage(page);
 }
diff --git a/fpdfsdk/fpdf_editpage.cpp b/fpdfsdk/fpdf_editpage.cpp
index e99218d..5f64700 100644
--- a/fpdfsdk/fpdf_editpage.cpp
+++ b/fpdfsdk/fpdf_editpage.cpp
@@ -859,17 +859,11 @@
 }
 
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
-FPDFFormObj_GetMatrix(FPDF_PAGEOBJECT form_object,
-                      double* a,
-                      double* b,
-                      double* c,
-                      double* d,
-                      double* e,
-                      double* f) {
+FPDFFormObj_GetMatrix(FPDF_PAGEOBJECT form_object, FS_MATRIX* matrix) {
   CPDF_FormObject* pFormObj = CPDFFormObjectFromFPDFPageObject(form_object);
-  if (!pFormObj || !a || !b || !c || !d || !e || !f)
+  if (!pFormObj || !matrix)
     return false;
 
-  std::tie(*a, *b, *c, *d, *e, *f) = pFormObj->form_matrix().AsTuple();
+  FSMatrixFromCFXMatrix(pFormObj->form_matrix(), matrix);
   return true;
 }
diff --git a/fpdfsdk/fpdf_editpath.cpp b/fpdfsdk/fpdf_editpath.cpp
index b89c470..1783035 100644
--- a/fpdfsdk/fpdf_editpath.cpp
+++ b/fpdfsdk/fpdf_editpath.cpp
@@ -183,35 +183,28 @@
 }
 
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_GetMatrix(FPDF_PAGEOBJECT path,
-                                                       double* a,
-                                                       double* b,
-                                                       double* c,
-                                                       double* d,
-                                                       double* e,
-                                                       double* f) {
-  if (!path || !a || !b || !c || !d || !e || !f)
+                                                       FS_MATRIX* matrix) {
+  if (!path || !matrix)
     return false;
 
   CPDF_PathObject* pPathObj = CPDFPathObjectFromFPDFPageObject(path);
   if (!pPathObj)
     return false;
 
-  std::tie(*a, *b, *c, *d, *e, *f) = pPathObj->matrix().AsTuple();
+  FSMatrixFromCFXMatrix(pPathObj->matrix(), matrix);
   return true;
 }
 
-FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_SetMatrix(FPDF_PAGEOBJECT path,
-                                                       double a,
-                                                       double b,
-                                                       double c,
-                                                       double d,
-                                                       double e,
-                                                       double f) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFPath_SetMatrix(FPDF_PAGEOBJECT path, const FS_MATRIX* matrix) {
+  if (!matrix)
+    return false;
+
   CPDF_PathObject* pPathObj = CPDFPathObjectFromFPDFPageObject(path);
   if (!pPathObj)
     return false;
 
-  pPathObj->set_matrix(CFX_Matrix(a, b, c, d, e, f));
+  pPathObj->set_matrix(CFXMatrixFromFSMatrix(*matrix));
   pPathObj->SetDirty(true);
   return true;
 }
diff --git a/fpdfsdk/fpdf_edittext.cpp b/fpdfsdk/fpdf_edittext.cpp
index 366d6c1..9421b49 100644
--- a/fpdfsdk/fpdf_edittext.cpp
+++ b/fpdfsdk/fpdf_edittext.cpp
@@ -511,26 +511,21 @@
 }
 
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFTextObj_GetMatrix(FPDF_PAGEOBJECT text,
-                                                          double* a,
-                                                          double* b,
-                                                          double* c,
-                                                          double* d,
-                                                          double* e,
-                                                          double* f) {
-  if (!a || !b || !c || !d || !e || !f)
+                                                          FS_MATRIX* matrix) {
+  if (!matrix)
     return false;
 
   CPDF_TextObject* pTextObj = CPDFTextObjectFromFPDFPageObject(text);
   if (!pTextObj)
     return false;
 
-  std::tie(*a, *b, *c, *d, *e, *f) = pTextObj->GetTextMatrix().AsTuple();
+  FSMatrixFromCFXMatrix(pTextObj->GetTextMatrix(), matrix);
   return true;
 }
 
-FPDF_EXPORT double FPDF_CALLCONV FPDFTextObj_GetFontSize(FPDF_PAGEOBJECT text) {
+FPDF_EXPORT float FPDF_CALLCONV FPDFTextObj_GetFontSize(FPDF_PAGEOBJECT text) {
   CPDF_TextObject* pTextObj = CPDFTextObjectFromFPDFPageObject(text);
-  return pTextObj ? pTextObj->GetFontSize() : 0;
+  return pTextObj ? pTextObj->GetFontSize() : 0.0f;
 }
 
 FPDF_EXPORT unsigned long FPDF_CALLCONV
diff --git a/fpdfsdk/fpdf_text.cpp b/fpdfsdk/fpdf_text.cpp
index a7f97dc..1dca39d 100644
--- a/fpdfsdk/fpdf_text.cpp
+++ b/fpdfsdk/fpdf_text.cpp
@@ -196,11 +196,11 @@
   return true;
 }
 
-FPDF_EXPORT double FPDF_CALLCONV FPDFText_GetCharAngle(FPDF_TEXTPAGE text_page,
-                                                       int index) {
+FPDF_EXPORT float FPDF_CALLCONV FPDFText_GetCharAngle(FPDF_TEXTPAGE text_page,
+                                                      int index) {
   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
   if (!textpage)
-    return -1;
+    return -1.0f;
 
   FPDF_CHAR_INFO charinfo;
   textpage->GetCharInfo(index, &charinfo);
@@ -210,7 +210,7 @@
   // | c  d  0 |    | sin(t)   cos(t)  0 |
   // | e  f  1 |    |   0        0     1 |
   // Calculate the angle of the vector
-  double angle = atan2(charinfo.m_Matrix.c, charinfo.m_Matrix.a);
+  float angle = atan2f(charinfo.m_Matrix.c, charinfo.m_Matrix.a);
   if (angle < 0)
     angle = 2 * FX_PI + angle;
 
@@ -240,13 +240,8 @@
 }
 
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
-FPDFText_GetLooseCharBox(FPDF_TEXTPAGE text_page,
-                         int index,
-                         double* left,
-                         double* right,
-                         double* bottom,
-                         double* top) {
-  if (!left || !right || !bottom || !top)
+FPDFText_GetLooseCharBox(FPDF_TEXTPAGE text_page, int index, FS_RECTF* rect) {
+  if (!rect)
     return false;
 
   CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
@@ -270,10 +265,10 @@
       short vert_width = pCIDFont->GetVertWidth(cid);
       double height = vert_width * charinfo.m_FontSize / 1000.0;
 
-      *left = charinfo.m_Origin.x + offsetx;
-      *right = *left + charinfo.m_FontSize;
-      *bottom = charinfo.m_Origin.y + offsety;
-      *top = *bottom + height;
+      rect->left = charinfo.m_Origin.x + offsetx;
+      rect->right = rect->left + charinfo.m_FontSize;
+      rect->bottom = charinfo.m_Origin.y + offsety;
+      rect->top = rect->bottom + height;
       return true;
     }
 
@@ -283,19 +278,19 @@
       float width = charinfo.m_pTextObj->GetCharWidth(charinfo.m_Charcode);
       float font_scale = charinfo.m_FontSize / (ascent - descent);
 
-      *left = charinfo.m_Origin.x;
-      *right = charinfo.m_Origin.x + (is_vert_writing ? -width : width);
-      *bottom = charinfo.m_Origin.y + descent * font_scale;
-      *top = charinfo.m_Origin.y + ascent * font_scale;
+      rect->left = charinfo.m_Origin.x;
+      rect->right = charinfo.m_Origin.x + (is_vert_writing ? -width : width);
+      rect->bottom = charinfo.m_Origin.y + descent * font_scale;
+      rect->top = charinfo.m_Origin.y + ascent * font_scale;
       return true;
     }
   }
 
   // Fallback to the tight bounds in empty text scenarios, or bad font metrics
-  *left = charinfo.m_CharBox.left;
-  *right = charinfo.m_CharBox.right;
-  *bottom = charinfo.m_CharBox.bottom;
-  *top = charinfo.m_CharBox.top;
+  rect->left = charinfo.m_CharBox.left;
+  rect->right = charinfo.m_CharBox.right;
+  rect->bottom = charinfo.m_CharBox.bottom;
+  rect->top = charinfo.m_CharBox.top;
   return true;
 }
 
diff --git a/fpdfsdk/fpdf_text_embeddertest.cpp b/fpdfsdk/fpdf_text_embeddertest.cpp
index ff3c2cb..edd4fd9 100644
--- a/fpdfsdk/fpdf_text_embeddertest.cpp
+++ b/fpdfsdk/fpdf_text_embeddertest.cpp
@@ -125,46 +125,29 @@
   EXPECT_NEAR(49.844, bottom, 0.001);
   EXPECT_NEAR(55.520, top, 0.001);
 
-  left = 4.0;
-  right = 3.0;
-  bottom = 2.0;
-  top = 1.0;
-  EXPECT_FALSE(
-      FPDFText_GetLooseCharBox(nullptr, 4, &left, &right, &bottom, &top));
-  EXPECT_DOUBLE_EQ(4.0, left);
-  EXPECT_DOUBLE_EQ(3.0, right);
-  EXPECT_DOUBLE_EQ(2.0, bottom);
-  EXPECT_DOUBLE_EQ(1.0, top);
-  EXPECT_FALSE(
-      FPDFText_GetLooseCharBox(textpage, -1, &left, &right, &bottom, &top));
-  EXPECT_DOUBLE_EQ(4.0, left);
-  EXPECT_DOUBLE_EQ(3.0, right);
-  EXPECT_DOUBLE_EQ(2.0, bottom);
-  EXPECT_DOUBLE_EQ(1.0, top);
-  EXPECT_FALSE(
-      FPDFText_GetLooseCharBox(textpage, 55, &left, &right, &bottom, &top));
-  EXPECT_DOUBLE_EQ(4.0, left);
-  EXPECT_DOUBLE_EQ(3.0, right);
-  EXPECT_DOUBLE_EQ(2.0, bottom);
-  EXPECT_DOUBLE_EQ(1.0, top);
-  EXPECT_FALSE(
-      FPDFText_GetLooseCharBox(textpage, 4, nullptr, &right, &bottom, &top));
-  EXPECT_FALSE(
-      FPDFText_GetLooseCharBox(textpage, 4, &left, nullptr, &bottom, &top));
-  EXPECT_FALSE(
-      FPDFText_GetLooseCharBox(textpage, 4, &left, &right, nullptr, &top));
-  EXPECT_FALSE(
-      FPDFText_GetLooseCharBox(textpage, 4, &left, &right, &bottom, nullptr));
-  EXPECT_FALSE(FPDFText_GetLooseCharBox(textpage, 4, nullptr, nullptr, nullptr,
-                                        nullptr));
+  FS_RECTF rect = {4.0f, 1.0f, 3.0f, 2.0f};
+  EXPECT_FALSE(FPDFText_GetLooseCharBox(nullptr, 4, &rect));
+  EXPECT_FLOAT_EQ(4.0f, rect.left);
+  EXPECT_FLOAT_EQ(3.0f, rect.right);
+  EXPECT_FLOAT_EQ(2.0f, rect.bottom);
+  EXPECT_FLOAT_EQ(1.0f, rect.top);
+  EXPECT_FALSE(FPDFText_GetLooseCharBox(textpage, -1, &rect));
+  EXPECT_FLOAT_EQ(4.0f, rect.left);
+  EXPECT_FLOAT_EQ(3.0f, rect.right);
+  EXPECT_FLOAT_EQ(2.0f, rect.bottom);
+  EXPECT_FLOAT_EQ(1.0f, rect.top);
+  EXPECT_FALSE(FPDFText_GetLooseCharBox(textpage, 55, &rect));
+  EXPECT_FLOAT_EQ(4.0f, rect.left);
+  EXPECT_FLOAT_EQ(3.0f, rect.right);
+  EXPECT_FLOAT_EQ(2.0f, rect.bottom);
+  EXPECT_FLOAT_EQ(1.0f, rect.top);
+  EXPECT_FALSE(FPDFText_GetLooseCharBox(textpage, 4, nullptr));
 
-  EXPECT_TRUE(
-      FPDFText_GetLooseCharBox(textpage, 4, &left, &right, &bottom, &top));
-  EXPECT_NEAR(40.664, left, 0.001);
-  EXPECT_NEAR(46.664, right, 0.001);
-  EXPECT_NEAR(47.667, bottom, 0.001);
-  EXPECT_NEAR(59.667, top, 0.001);
-  EXPECT_NEAR(12.000, top - bottom, 0.001);
+  EXPECT_TRUE(FPDFText_GetLooseCharBox(textpage, 4, &rect));
+  EXPECT_FLOAT_EQ(40.664001f, rect.left);
+  EXPECT_FLOAT_EQ(46.664001f, rect.right);
+  EXPECT_FLOAT_EQ(47.667271f, rect.bottom);
+  EXPECT_FLOAT_EQ(59.667271f, rect.top);
 
   double x = 0.0;
   double y = 0.0;
@@ -262,25 +245,18 @@
   EXPECT_NEAR(8.668, x, 0.001);
   EXPECT_NEAR(160.492, y, 0.001);
 
-  double left = 0.0;
-  double right = 0.0;
-  double bottom = 0.0;
-  double top = 0.0;
-  EXPECT_TRUE(
-      FPDFText_GetLooseCharBox(textpage, 1, &left, &right, &bottom, &top));
-  EXPECT_NEAR(4, left, 0.001);
-  EXPECT_NEAR(16, right, 0.001);
-  EXPECT_NEAR(178.984, bottom, 0.001);
-  EXPECT_NEAR(170.308, top, 0.001);
-  EXPECT_NEAR(12.000, right - left, 0.001);
+  FS_RECTF rect;
+  EXPECT_TRUE(FPDFText_GetLooseCharBox(textpage, 1, &rect));
+  EXPECT_NEAR(4, rect.left, 0.001);
+  EXPECT_NEAR(16, rect.right, 0.001);
+  EXPECT_NEAR(178.984, rect.bottom, 0.001);
+  EXPECT_NEAR(170.308, rect.top, 0.001);
 
-  EXPECT_TRUE(
-      FPDFText_GetLooseCharBox(textpage, 2, &left, &right, &bottom, &top));
-  EXPECT_NEAR(4, left, 0.001);
-  EXPECT_NEAR(16, right, 0.001);
-  EXPECT_NEAR(170.308, bottom, 0.001);
-  EXPECT_NEAR(159.292, top, 0.001);
-  EXPECT_NEAR(12.000, right - left, 0.001);
+  EXPECT_TRUE(FPDFText_GetLooseCharBox(textpage, 2, &rect));
+  EXPECT_NEAR(4, rect.left, 0.001);
+  EXPECT_NEAR(16, rect.right, 0.001);
+  EXPECT_NEAR(170.308, rect.bottom, 0.001);
+  EXPECT_NEAR(159.292, rect.top, 0.001);
 
   FPDFText_ClosePage(textpage);
   UnloadPage(page);
@@ -1323,9 +1299,10 @@
   // character.
   EXPECT_EQ(kHelloGoodbyeTextSize, FPDFText_CountChars(text_page));
 
-  EXPECT_EQ(-1, FPDFText_GetCharAngle(nullptr, 0));
-  EXPECT_EQ(-1, FPDFText_GetCharAngle(text_page, -1));
-  EXPECT_EQ(-1, FPDFText_GetCharAngle(text_page, kHelloGoodbyeTextSize + 1));
+  EXPECT_FLOAT_EQ(-1.0f, FPDFText_GetCharAngle(nullptr, 0));
+  EXPECT_FLOAT_EQ(-1.0f, FPDFText_GetCharAngle(text_page, -1));
+  EXPECT_FLOAT_EQ(-1.0f,
+                  FPDFText_GetCharAngle(text_page, kHelloGoodbyeTextSize + 1));
 
   // Test GetCharAngle for every quadrant
   EXPECT_NEAR(FX_PI / 4.0, FPDFText_GetCharAngle(text_page, 0), 0.001);
diff --git a/fpdfsdk/fpdf_transformpage.cpp b/fpdfsdk/fpdf_transformpage.cpp
index 496b89e..cc26888 100644
--- a/fpdfsdk/fpdf_transformpage.cpp
+++ b/fpdfsdk/fpdf_transformpage.cpp
@@ -220,7 +220,7 @@
   text_buf << "q ";
 
   if (clipRect) {
-    CFX_FloatRect rect = CFXFloatRectFromFSRECTF(*clipRect);
+    CFX_FloatRect rect = CFXFloatRectFromFSRectF(*clipRect);
     rect.Normalize();
 
     WriteFloat(text_buf, rect.left) << " ";
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index c25d4d1..e69d237 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -382,7 +382,7 @@
   if (!pPage)
     return false;
 
-  *rect = FSRECTFFromCFXFloatRect(pPage->GetBBox());
+  *rect = FSRectFFromCFXFloatRect(pPage->GetBBox());
   return true;
 }
 
@@ -687,7 +687,7 @@
 
   CFX_FloatRect clipping_rect;
   if (clipping)
-    clipping_rect = CFXFloatRectFromFSRECTF(*clipping);
+    clipping_rect = CFXFloatRectFromFSRectF(*clipping);
   FX_RECT clip_rect = clipping_rect.ToFxRect();
 
   const FX_RECT rect(0, 0, pPage->GetPageWidth(), pPage->GetPageHeight());
diff --git a/public/fpdf_annot.h b/public/fpdf_annot.h
index 8dbe991..cae6cfd 100644
--- a/public/fpdf_annot.h
+++ b/public/fpdf_annot.h
@@ -528,16 +528,14 @@
 //    hHandle     -   handle to the form fill module, returned by
 //                    FPDFDOC_InitFormFillEnvironment().
 //    page        -   handle to the page, returned by FPDF_LoadPage function.
-//    page_x      -   X position in PDF "user space".
-//    page_y      -   Y position in PDF "user space".
+//    point       -   position in PDF "user space".
 //
 // Returns the interactive form annotation whose rectangle contains the given
 // coordinates on the page. If there is no such annotation, return NULL.
 FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV
 FPDFAnnot_GetFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
                               FPDF_PAGE page,
-                              double page_x,
-                              double page_y);
+                              const FS_POINTF* point);
 
 // Experimental API.
 // Get the number of options in the |annot|'s "Opt" dictionary. Intended for
diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h
index 5974ab6..2bf769b 100644
--- a/public/fpdf_edit.h
+++ b/public/fpdf_edit.h
@@ -1006,13 +1006,8 @@
 // Experimental API.
 // Get the transform matrix of a path.
 //
-//   path - handle to a path.
-//   a    - matrix value.
-//   b    - matrix value.
-//   c    - matrix value.
-//   d    - matrix value.
-//   e    - matrix value.
-//   f    - matrix value.
+//   path   - handle to a path.
+//   matrix - pointer to struct to receive the matrix value.
 //
 // The matrix is composed as:
 //   |a c e|
@@ -1021,23 +1016,13 @@
 //
 // Returns TRUE on success.
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_GetMatrix(FPDF_PAGEOBJECT path,
-                                                       double* a,
-                                                       double* b,
-                                                       double* c,
-                                                       double* d,
-                                                       double* e,
-                                                       double* f);
+                                                       FS_MATRIX* matrix);
 
 // Experimental API.
 // Set the transform matrix of a path.
 //
-//   path - handle to a path.
-//   a    - matrix value.
-//   b    - matrix value.
-//   c    - matrix value.
-//   d    - matrix value.
-//   e    - matrix value.
-//   f    - matrix value.
+//   path   - handle to a path.
+//   matrix - pointer to struct with the matrix value.
 //
 // The matrix is composed as:
 //   |a c e|
@@ -1046,12 +1031,7 @@
 //
 // Returns TRUE on success.
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_SetMatrix(FPDF_PAGEOBJECT path,
-                                                       double a,
-                                                       double b,
-                                                       double c,
-                                                       double d,
-                                                       double e,
-                                                       double f);
+                                                       const FS_MATRIX* matrix);
 
 // Create a new text object using one of the standard PDF fonts.
 //
@@ -1110,13 +1090,8 @@
 // Experimental API.
 // Get the transform matrix of a text object.
 //
-//   text - handle to a text.
-//   a    - matrix value.
-//   b    - matrix value.
-//   c    - matrix value.
-//   d    - matrix value.
-//   e    - matrix value.
-//   f    - matrix value.
+//   text   - handle to a text.
+//   matrix - pointer to struct with the matrix value.
 //
 // The matrix is composed as:
 //   |a c e|
@@ -1125,12 +1100,7 @@
 //
 // Returns TRUE on success.
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFTextObj_GetMatrix(FPDF_PAGEOBJECT text,
-                                                          double* a,
-                                                          double* b,
-                                                          double* c,
-                                                          double* d,
-                                                          double* e,
-                                                          double* f);
+                                                          FS_MATRIX* matrix);
 
 // Experimental API.
 // Get the font size of a text object.
@@ -1139,7 +1109,7 @@
 //
 // Returns the font size of the text object, measured in points (about 1/72
 // inch) on success; 0 on failure.
-FPDF_EXPORT double FPDF_CALLCONV FPDFTextObj_GetFontSize(FPDF_PAGEOBJECT text);
+FPDF_EXPORT float FPDF_CALLCONV FPDFTextObj_GetFontSize(FPDF_PAGEOBJECT text);
 
 // Close a loaded PDF font.
 //
@@ -1228,12 +1198,7 @@
 // Get the transform matrix of a form object.
 //
 //   form_object - handle to a form.
-//   a           - pointer to out variable to receive matrix value.
-//   b           - pointer to out variable to receive matrix value.
-//   c           - pointer to out variable to receive matrix value.
-//   d           - pointer to out variable to receive matrix value.
-//   e           - pointer to out variable to receive matrix value.
-//   f           - pointer to out variable to receive matrix value.
+//   matrix      - pointer to struct to receive the matrix value.
 //
 // The matrix is composed as:
 //   |a c e|
@@ -1242,13 +1207,7 @@
 //
 // Returns TRUE on success.
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
-FPDFFormObj_GetMatrix(FPDF_PAGEOBJECT form_object,
-                      double* a,
-                      double* b,
-                      double* c,
-                      double* d,
-                      double* e,
-                      double* f);
+FPDFFormObj_GetMatrix(FPDF_PAGEOBJECT form_object, FS_MATRIX* matrix);
 
 #ifdef __cplusplus
 }  // extern "C"
diff --git a/public/fpdf_text.h b/public/fpdf_text.h
index d71e146..7ab5053 100644
--- a/public/fpdf_text.h
+++ b/public/fpdf_text.h
@@ -206,8 +206,8 @@
 //          On success, return the angle value in radian. Value will always be
 //          greater or equal to 0. If |text_page| is invalid, or if |index| is
 //          out of bounds, then return -1.
-FPDF_EXPORT double FPDF_CALLCONV FPDFText_GetCharAngle(FPDF_TEXTPAGE text_page,
-                                                       int index);
+FPDF_EXPORT float FPDF_CALLCONV FPDFText_GetCharAngle(FPDF_TEXTPAGE text_page,
+                                                      int index);
 
 // Function: FPDFText_GetCharBox
 //          Get bounding box of a particular character.
@@ -246,28 +246,16 @@
 //          text_page   -   Handle to a text page information structure.
 //                          Returned by FPDFText_LoadPage function.
 //          index       -   Zero-based index of the character.
-//          left        -   Pointer to a double number receiving left position
-//                          of the character box.
-//          right       -   Pointer to a double number receiving right position
-//                          of the character box.
-//          bottom      -   Pointer to a double number receiving bottom position
-//                          of the character box.
-//          top         -   Pointer to a double number receiving top position of
-//                          the character box.
+//          rect        -   Pointer to a FS_RECTF receiving the character box.
 // Return Value:
-//          On success, return TRUE and fill in |left|, |right|, |bottom|, and
-//          |top|. If |text_page| is invalid, or if |index| is out of bounds,
-//          then return FALSE, and the out parameters remain unmodified.
+//          On success, return TRUE and fill in |rect|. If |text_page| is
+//          invalid, or if |index| is out of bounds, then return FALSE, and the
+//          |rect| out parameter remains unmodified.
 // Comments:
 //          All positions are measured in PDF "user space".
 //
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
-FPDFText_GetLooseCharBox(FPDF_TEXTPAGE text_page,
-                         int index,
-                         double* left,
-                         double* right,
-                         double* bottom,
-                         double* top);
+FPDFText_GetLooseCharBox(FPDF_TEXTPAGE text_page, int index, FS_RECTF* rect);
 
 // Function: FPDFText_GetCharOrigin
 //          Get origin of a particular character.
diff --git a/public/fpdfview.h b/public/fpdfview.h
index ef1d0e0..5c3fe43 100644
--- a/public/fpdfview.h
+++ b/public/fpdfview.h
@@ -158,6 +158,15 @@
 // Const Pointer to FS_SIZEF structure.
 typedef const FS_SIZEF* FS_LPCSIZEF;
 
+// 2D Point. Coordinate system agnostic.
+typedef struct FS_POINTF_ {
+  float x;
+  float y;
+} * FS_LPPOINTF, FS_POINTF;
+
+// Const Pointer to FS_POINTF structure.
+typedef const FS_POINTF* FS_LPCPOINTF;
+
 // Annotation enums.
 typedef int FPDF_ANNOTATION_SUBTYPE;
 typedef int FPDF_ANNOT_APPEARANCEMODE;