Fix incorrect matrix outputs in CPDF_PageContentGenerator
When CPDF_PageContentGenerator generates content stream data for a page
object, it currently does not take the object's container's current
transformation matrix into account. As a result, the generated output
effectively has the CTM applied twice for page objects whose CTM is not
the identity matrix, as shown in recently added PDFEditImgTest cases.
Change CPDF_PageContentGenerator to take the CTM into account for images
and forms. Then update the related PDFEditImgTest cases so they pass
with the expected results. Add TODOs for CPDF_PageContentGenerator
methods that process text and paths, as there are no associated tests
for those.
Along the way, use more local matrix variables to avoid repeated calls
to getters.
Bug: pdfium:2132
Change-Id: I8d4c783ddee5c44dfeca32ec5575d228572e2417
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/116933
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
index 617891c..c427478 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -174,8 +174,10 @@
// Set the default graphic state values
buf << "q\n";
- if (!m_pObjHolder->GetLastCTM().IsIdentity())
- WriteMatrix(buf, m_pObjHolder->GetLastCTM().GetInverse()) << " cm\n";
+ const CFX_Matrix& ctm = m_pObjHolder->GetLastCTM();
+ if (!ctm.IsIdentity()) {
+ WriteMatrix(buf, ctm.GetInverse()) << " cm\n";
+ }
ProcessDefaultGraphics(&buf);
streams[dirty_stream] = std::move(buf);
@@ -397,8 +399,8 @@
void CPDF_PageContentGenerator::ProcessImage(fxcrt::ostringstream* buf,
CPDF_ImageObject* pImageObj) {
- if ((pImageObj->matrix().a == 0 && pImageObj->matrix().b == 0) ||
- (pImageObj->matrix().c == 0 && pImageObj->matrix().d == 0)) {
+ CFX_Matrix matrix = pImageObj->matrix();
+ if ((matrix.a == 0 && matrix.b == 0) || (matrix.c == 0 && matrix.d == 0)) {
return;
}
@@ -411,7 +413,12 @@
return;
*buf << "q ";
- WriteMatrix(*buf, pImageObj->matrix()) << " cm ";
+
+ const CFX_Matrix& ctm = m_pObjHolder->GetLastCTM();
+ if (!ctm.IsIdentity()) {
+ matrix.Concat(ctm.GetInverse());
+ }
+ WriteMatrix(*buf, matrix) << " cm ";
bool bWasInline = pStream->IsInline();
if (bWasInline)
@@ -430,8 +437,8 @@
void CPDF_PageContentGenerator::ProcessForm(fxcrt::ostringstream* buf,
CPDF_FormObject* pFormObj) {
- if ((pFormObj->form_matrix().a == 0 && pFormObj->form_matrix().b == 0) ||
- (pFormObj->form_matrix().c == 0 && pFormObj->form_matrix().d == 0)) {
+ CFX_Matrix matrix = pFormObj->form_matrix();
+ if ((matrix.a == 0 && matrix.b == 0) || (matrix.c == 0 && matrix.d == 0)) {
return;
}
@@ -443,7 +450,13 @@
pFormObj->SetResourceName(name);
*buf << "q\n";
- WriteMatrix(*buf, pFormObj->form_matrix()) << " cm ";
+
+ const CFX_Matrix& ctm = m_pObjHolder->GetLastCTM();
+ if (!ctm.IsIdentity()) {
+ matrix.Concat(ctm.GetInverse());
+ }
+ WriteMatrix(*buf, matrix) << " cm ";
+
*buf << "/" << PDF_NameEncode(name) << " Do Q\n";
}
@@ -502,6 +515,8 @@
CPDF_PathObject* pPathObj) {
ProcessGraphics(buf, pPathObj);
+ // TODO(crbug.com/pdfium/2132): Does this need to take the current
+ // transformation matrix in `m_pObjHolder` into account?
WriteMatrix(*buf, pPathObj->matrix()) << " cm ";
ProcessPathPoints(buf, &pPathObj->path());
@@ -654,6 +669,8 @@
CPDF_TextObject* pTextObj) {
ProcessGraphics(buf, pTextObj);
*buf << "BT ";
+ // TODO(crbug.com/pdfium/2132): Does this need to take the current
+ // transformation matrix in `m_pObjHolder` into account?
WriteMatrix(*buf, pTextObj->GetTextMatrix()) << " Tm ";
RetainPtr<CPDF_Font> pFont(pTextObj->GetFont());
if (!pFont)
diff --git a/fpdfsdk/fpdf_editimg_embeddertest.cpp b/fpdfsdk/fpdf_editimg_embeddertest.cpp
index c06d495..d16cef3 100644
--- a/fpdfsdk/fpdf_editimg_embeddertest.cpp
+++ b/fpdfsdk/fpdf_editimg_embeddertest.cpp
@@ -219,9 +219,7 @@
UnloadPage(page);
- // TODO(crbug.com/pdfium/2132): Should be `kExpectedChecksum`.
- constexpr char kWrongChecksum[] = "d01c62c9ee094f5be545f006148808b5";
- VerifySavedDocument(kExpectedWidth, kExpectedHeight, kWrongChecksum);
+ VerifySavedDocument(kExpectedWidth, kExpectedHeight, kExpectedChecksum);
}
TEST_F(PDFEditImgTest, GetAndSetMatrixForFormWithImage) {
@@ -289,7 +287,5 @@
UnloadPage(page);
- // TODO(crbug.com/pdfium/2132): Should be `kExpectedChecksum`.
- constexpr char kWrongChecksum[] = "308e2263f01744b2749d68a9ca711fc6";
- VerifySavedDocument(kExpectedWidth, kExpectedHeight, kWrongChecksum);
+ VerifySavedDocument(kExpectedWidth, kExpectedHeight, kExpectedChecksum);
}