Teach FPDFPageObj_SetMatrix() to set the matrix for text objects.

Convert an embedder test to use the new API capability, instead of
accessing the internal CPDF_TextObject directly.

Change-Id: Ic1cd9a5d95a3760da39fd00c1d9d388c1e2aa23d
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/82614
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_textobject.cpp b/core/fpdfapi/page/cpdf_textobject.cpp
index eca37ab..edc2f5f 100644
--- a/core/fpdfapi/page/cpdf_textobject.cpp
+++ b/core/fpdfapi/page/cpdf_textobject.cpp
@@ -155,15 +155,7 @@
 }
 
 void CPDF_TextObject::Transform(const CFX_Matrix& matrix) {
-  CFX_Matrix text_matrix = GetTextMatrix() * matrix;
-
-  float* pTextMatrix = m_TextState.GetMutableMatrix();
-  pTextMatrix[0] = text_matrix.a;
-  pTextMatrix[1] = text_matrix.c;
-  pTextMatrix[2] = text_matrix.b;
-  pTextMatrix[3] = text_matrix.d;
-  m_Pos = CFX_PointF(text_matrix.e, text_matrix.f);
-  CalcPositionData(0);
+  SetTextMatrix(GetTextMatrix() * matrix);
   SetDirty(true);
 }
 
@@ -185,6 +177,16 @@
                     pTextMatrix[3], m_Pos.x, m_Pos.y);
 }
 
+void CPDF_TextObject::SetTextMatrix(const CFX_Matrix& matrix) {
+  float* pTextMatrix = m_TextState.GetMutableMatrix();
+  pTextMatrix[0] = matrix.a;
+  pTextMatrix[1] = matrix.c;
+  pTextMatrix[2] = matrix.b;
+  pTextMatrix[3] = matrix.d;
+  m_Pos = CFX_PointF(matrix.e, matrix.f);
+  CalcPositionData(0);
+}
+
 void CPDF_TextObject::SetSegments(const ByteString* pStrs,
                                   const std::vector<float>& kernings,
                                   size_t nSegs) {
diff --git a/core/fpdfapi/page/cpdf_textobject.h b/core/fpdfapi/page/cpdf_textobject.h
index c650352..2fe269f 100644
--- a/core/fpdfapi/page/cpdf_textobject.h
+++ b/core/fpdfapi/page/cpdf_textobject.h
@@ -30,7 +30,7 @@
   CPDF_TextObject();
   ~CPDF_TextObject() override;
 
-  // CPDF_PageObject
+  // CPDF_PageObject:
   Type GetType() const override;
   void Transform(const CFX_Matrix& matrix) override;
   bool IsText() const override;
@@ -66,6 +66,9 @@
   const std::vector<uint32_t>& GetCharCodes() const { return m_CharCodes; }
   const std::vector<float>& GetCharPositions() const { return m_CharPos; }
 
+  // Caller is expected to call SetDirty(true) when done changing the object.
+  void SetTextMatrix(const CFX_Matrix& matrix);
+
   void SetSegments(const ByteString* pStrs,
                    const std::vector<float>& kernings,
                    size_t nSegs);
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp
index 11fca24..f16f5d5 100644
--- a/fpdfsdk/fpdf_edit_embeddertest.cpp
+++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -9,7 +9,6 @@
 
 #include "build/build_config.h"
 #include "core/fpdfapi/font/cpdf_font.h"
-#include "core/fpdfapi/page/cpdf_formobject.h"
 #include "core/fpdfapi/page/cpdf_page.h"
 #include "core/fpdfapi/page/cpdf_pageobject.h"
 #include "core/fpdfapi/parser/cpdf_array.h"
@@ -2211,7 +2210,8 @@
   EXPECT_TRUE(text_object1);
   ScopedFPDFWideString text1 = GetFPDFWideString(kBottomText);
   EXPECT_TRUE(FPDFText_SetText(text_object1, text1.get()));
-  FPDFPageObj_Transform(text_object1, 1, 0, 0, 1, 20, 20);
+  static constexpr FS_MATRIX kMatrix1{1, 0, 0, 1, 20, 20};
+  EXPECT_TRUE(FPDFPageObj_SetMatrix(text_object1, &kMatrix1));
   FPDFPage_InsertObject(page, text_object1);
   EXPECT_TRUE(FPDFPage_GenerateContent(page));
   {
diff --git a/fpdfsdk/fpdf_editpage.cpp b/fpdfsdk/fpdf_editpage.cpp
index dc0f8a2..b060a1a 100644
--- a/fpdfsdk/fpdf_editpage.cpp
+++ b/fpdfsdk/fpdf_editpage.cpp
@@ -652,7 +652,8 @@
   CFX_Matrix cmatrix = CFXMatrixFromFSMatrix(*matrix);
   switch (pPageObj->GetType()) {
     case CPDF_PageObject::TEXT:
-      return false;
+      pPageObj->AsText()->SetTextMatrix(cmatrix);
+      break;
     case CPDF_PageObject::PATH:
       pPageObj->AsPath()->set_matrix(cmatrix);
       break;