blob: 3ec157c1647c0f45a7c9cb6166c44468c753d59d [file] [log] [blame]
Tom Sepezd483eb42016-01-06 10:03:59 -08001// Copyright 2016 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Dan Sinclair85c8e7f2016-11-21 13:50:32 -05005#include <memory>
6#include <string>
Nicolas Penad03ca422017-03-06 13:54:33 -05007#include <utility>
Jane Liu548334e2017-08-03 16:33:40 -04008#include <vector>
Dan Sinclair85c8e7f2016-11-21 13:50:32 -05009
Lei Zhange4cdac52019-04-30 16:45:57 +000010#include "build/build_config.h"
Nicolas Penabe90aae2017-02-27 10:41:41 -050011#include "core/fpdfapi/font/cpdf_font.h"
Nicolas Penaa4ad01f2017-02-15 16:26:48 -050012#include "core/fpdfapi/page/cpdf_page.h"
Henrique Nakashima6eb79392018-06-12 20:27:35 +000013#include "core/fpdfapi/page/cpdf_pageobject.h"
Nicolas Penabe90aae2017-02-27 10:41:41 -050014#include "core/fpdfapi/parser/cpdf_array.h"
Nicolas Penaa4ad01f2017-02-15 16:26:48 -050015#include "core/fpdfapi/parser/cpdf_dictionary.h"
Nicolas Penad03ca422017-03-06 13:54:33 -050016#include "core/fpdfapi/parser/cpdf_number.h"
Nicolas Penabe90aae2017-02-27 10:41:41 -050017#include "core/fpdfapi/parser/cpdf_stream.h"
Artem Strygineababa12018-06-06 12:31:18 +000018#include "core/fpdfapi/parser/cpdf_stream_acc.h"
Tom Sepez6c57cda2021-07-23 19:41:57 +000019#include "core/fxcrt/fx_codepage.h"
Nicolas Pena0fc185e2017-02-08 12:13:20 -050020#include "core/fxcrt/fx_system.h"
Lei Zhang0dcb8fd2019-02-07 00:46:04 +000021#include "core/fxge/fx_font.h"
Dan Sinclair00d47a62018-03-28 18:39:04 +000022#include "fpdfsdk/cpdfsdk_helpers.h"
Tom Sepeze08d2b12018-04-25 18:49:32 +000023#include "public/cpp/fpdf_scopers.h"
Jane Liueda65252017-06-07 11:31:27 -040024#include "public/fpdf_annot.h"
Tom Sepezd483eb42016-01-06 10:03:59 -080025#include "public/fpdf_edit.h"
26#include "public/fpdfview.h"
27#include "testing/embedder_test.h"
Hui Yingstb4baceb2020-04-28 23:46:10 +000028#include "testing/embedder_test_constants.h"
Lei Zhangb6992dd2019-02-05 23:30:20 +000029#include "testing/fx_string_testhelpers.h"
Tom Sepez0aec19b2016-01-07 12:22:44 -080030#include "testing/gmock/include/gmock/gmock-matchers.h"
Tom Sepezd483eb42016-01-06 10:03:59 -080031#include "testing/gtest/include/gtest/gtest.h"
Hui Yingst8e88e382020-11-02 18:19:56 +000032#include "testing/utils/file_util.h"
Lei Zhang4c64e962019-02-05 19:24:12 +000033#include "testing/utils/hash.h"
Hui Yingst8e88e382020-11-02 18:19:56 +000034#include "testing/utils/path_service.h"
Tom Sepez9c78c0d2021-01-27 20:13:14 +000035#include "third_party/base/check.h"
Tom Sepezd483eb42016-01-06 10:03:59 -080036
Hui Yingstb4baceb2020-04-28 23:46:10 +000037using pdfium::kHelloWorldChecksum;
38
39namespace {
40
Hui Yingst3b6136a2020-06-09 00:39:33 +000041const char kAllRemovedChecksum[] = "eee4600ac08b458ac7ac2320e225674c";
42
43const wchar_t kBottomText[] = L"I'm at the bottom of the page";
44
Hui Yingst5ce6a3f2020-11-11 02:29:09 +000045#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
46static constexpr char kBottomTextChecksum[] =
47 "5df7be86df1e18819723cdd9c81c2c7d";
Hui Yingst3b6136a2020-06-09 00:39:33 +000048#else
Hui Yingst5ce6a3f2020-11-11 02:29:09 +000049#if defined(OS_WIN)
50static constexpr char kBottomTextChecksum[] =
51 "08d1ff3e5a42801bee6077fd366bef00";
52#elif defined(OS_APPLE)
53static constexpr char kBottomTextChecksum[] =
54 "324e1db8164a040cf6104538baa95ba6";
55#else
56static constexpr char kBottomTextChecksum[] =
57 "eacaa24573b8ce997b3882595f096f00";
Hui Yingst3b6136a2020-06-09 00:39:33 +000058#endif
Hui Yingst5ce6a3f2020-11-11 02:29:09 +000059#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingstb4baceb2020-04-28 23:46:10 +000060
Hui Yingst08c40712020-04-29 01:37:35 +000061#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingst08c40712020-04-29 01:37:35 +000062const char kFirstRemovedChecksum[] = "0c79dc1065b1d06991e3ac4aaa35d25c";
Hui Yingst08c40712020-04-29 01:37:35 +000063#else
Hui Yingstb4baceb2020-04-28 23:46:10 +000064#if defined(OS_WIN)
65const char kFirstRemovedChecksum[] = "aae6c5334721f90ec30d3d59f4ef7deb";
Lei Zhang0c03d632020-07-30 17:05:36 +000066#elif defined(OS_APPLE)
Hui Yingstb4baceb2020-04-28 23:46:10 +000067const char kFirstRemovedChecksum[] = "17ca3778fd8bb395b46532f1fa17f702";
68#else
69const char kFirstRemovedChecksum[] = "b76df015fe88009c3c342395df96abf1";
70#endif
Hui Yingst08c40712020-04-29 01:37:35 +000071#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingstb4baceb2020-04-28 23:46:10 +000072
Hui Yingst3b6136a2020-06-09 00:39:33 +000073const wchar_t kLoadedFontText[] = L"I am testing my loaded font, WEE.";
74
Hui Yingst9d6ec8f2020-11-05 23:35:38 +000075#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
76const char kLoadedFontTextChecksum[] = "a1dffe52c1b9ded5fe8d77eb10d8cc19";
77#else
Hui Yingst3b6136a2020-06-09 00:39:33 +000078#if defined(OS_WIN)
79const char kLoadedFontTextChecksum[] = "d60ba39f9698e32360d99e727dd93165";
Lei Zhang0c03d632020-07-30 17:05:36 +000080#elif defined(OS_APPLE)
Hui Yingst3b6136a2020-06-09 00:39:33 +000081const char kLoadedFontTextChecksum[] = "fc921c0bbdde73986ac13c15a85db4c3";
82#else
83const char kLoadedFontTextChecksum[] = "70592859010ffbf532a2237b8118bcc4";
84#endif
Hui Yingst9d6ec8f2020-11-05 23:35:38 +000085#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingst3b6136a2020-06-09 00:39:33 +000086
87const char kRedRectangleChecksum[] = "66d02eaa6181e2c069ce2ea99beda497";
88
Lei Zhang85166512020-07-14 23:28:56 +000089// In embedded_images.pdf.
90const char kEmbeddedImage33Checksum[] = "cb3637934bb3b95a6e4ae1ea9eb9e56e";
91
Hui Yingstb4baceb2020-04-28 23:46:10 +000092} // namespace
93
Lei Zhangab41f252018-12-23 03:10:50 +000094class FPDFEditEmbedderTest : public EmbedderTest {
Nicolas Penad03ca422017-03-06 13:54:33 -050095 protected:
96 FPDF_DOCUMENT CreateNewDocument() {
Lei Zhang935fb862021-11-05 00:15:05 +000097 CreateEmptyDocumentWithoutFormFillEnvironment();
Lei Zhang38e2b0e2021-11-05 00:28:05 +000098 cpdf_doc_ = CPDFDocumentFromFPDFDocument(document());
99 return document();
Nicolas Penad03ca422017-03-06 13:54:33 -0500100 }
101
Lei Zhang710fa992018-05-25 16:24:48 +0000102 void CheckFontDescriptor(const CPDF_Dictionary* font_dict,
Nicolas Penad03ca422017-03-06 13:54:33 -0500103 int font_type,
104 bool bold,
105 bool italic,
Tom Sepez20c41a52018-08-29 23:53:53 +0000106 pdfium::span<const uint8_t> span) {
Lei Zhangb1ec2802018-05-25 21:55:24 +0000107 const CPDF_Dictionary* font_desc = font_dict->GetDictFor("FontDescriptor");
Nicolas Penad03ca422017-03-06 13:54:33 -0500108 ASSERT_TRUE(font_desc);
Lei Zhanga228ff32020-06-24 17:39:33 +0000109 EXPECT_EQ("FontDescriptor", font_desc->GetNameFor("Type"));
110 ByteString font_name = font_desc->GetNameFor("FontName");
111 EXPECT_FALSE(font_name.IsEmpty());
112 EXPECT_EQ(font_dict->GetNameFor("BaseFont"), font_name);
Nicolas Penad03ca422017-03-06 13:54:33 -0500113
114 // Check that the font descriptor has the required keys according to spec
115 // 1.7 Table 5.19
116 ASSERT_TRUE(font_desc->KeyExist("Flags"));
Dan Sinclair10e1f052017-09-28 15:59:42 -0400117
Nicolas Penad03ca422017-03-06 13:54:33 -0500118 int font_flags = font_desc->GetIntegerFor("Flags");
Lei Zhang44d03832019-10-18 18:45:31 +0000119 EXPECT_EQ(bold, FontStyleIsForceBold(font_flags));
Dan Sinclair10e1f052017-09-28 15:59:42 -0400120 EXPECT_EQ(italic, FontStyleIsItalic(font_flags));
121 EXPECT_TRUE(FontStyleIsNonSymbolic(font_flags));
Nicolas Penad03ca422017-03-06 13:54:33 -0500122 ASSERT_TRUE(font_desc->KeyExist("FontBBox"));
Nicolás Peña5f95f362017-09-28 13:00:45 +0900123
Lei Zhangb1ec2802018-05-25 21:55:24 +0000124 const CPDF_Array* fontBBox = font_desc->GetArrayFor("FontBBox");
Nicolás Peña5f95f362017-09-28 13:00:45 +0900125 ASSERT_TRUE(fontBBox);
Lei Zhangf40380f2018-10-12 18:31:51 +0000126 EXPECT_EQ(4u, fontBBox->size());
Nicolás Peña5f95f362017-09-28 13:00:45 +0900127 // Check that the coordinates are in the preferred order according to spec
128 // 1.7 Section 3.8.4
129 EXPECT_TRUE(fontBBox->GetIntegerAt(0) < fontBBox->GetIntegerAt(2));
130 EXPECT_TRUE(fontBBox->GetIntegerAt(1) < fontBBox->GetIntegerAt(3));
131
Nicolas Penad03ca422017-03-06 13:54:33 -0500132 EXPECT_TRUE(font_desc->KeyExist("ItalicAngle"));
133 EXPECT_TRUE(font_desc->KeyExist("Ascent"));
134 EXPECT_TRUE(font_desc->KeyExist("Descent"));
135 EXPECT_TRUE(font_desc->KeyExist("CapHeight"));
136 EXPECT_TRUE(font_desc->KeyExist("StemV"));
Ryan Harrison275e2602017-09-18 14:23:18 -0400137 ByteString present("FontFile");
138 ByteString absent("FontFile2");
Nicolas Penad03ca422017-03-06 13:54:33 -0500139 if (font_type == FPDF_FONT_TRUETYPE)
140 std::swap(present, absent);
141 EXPECT_TRUE(font_desc->KeyExist(present));
142 EXPECT_FALSE(font_desc->KeyExist(absent));
143
Artem Strygineababa12018-06-06 12:31:18 +0000144 auto streamAcc =
145 pdfium::MakeRetain<CPDF_StreamAcc>(font_desc->GetStreamFor(present));
146 streamAcc->LoadAllDataRaw();
147
Nicolas Penad03ca422017-03-06 13:54:33 -0500148 // Check that the font stream is the one that was provided
Tom Sepez20c41a52018-08-29 23:53:53 +0000149 ASSERT_EQ(span.size(), streamAcc->GetSize());
Nicolás Peña79eab232017-09-28 13:29:05 +0900150 if (font_type == FPDF_FONT_TRUETYPE) {
Tom Sepez20c41a52018-08-29 23:53:53 +0000151 ASSERT_EQ(static_cast<int>(span.size()),
Artem Strygineababa12018-06-06 12:31:18 +0000152 streamAcc->GetDict()->GetIntegerFor("Length1"));
Nicolás Peña79eab232017-09-28 13:29:05 +0900153 }
Artem Strygineababa12018-06-06 12:31:18 +0000154
155 const uint8_t* stream_data = streamAcc->GetData();
Tom Sepez20c41a52018-08-29 23:53:53 +0000156 for (size_t j = 0; j < span.size(); j++)
157 EXPECT_EQ(span[j], stream_data[j]) << " at byte " << j;
Nicolas Penad03ca422017-03-06 13:54:33 -0500158 }
159
Lei Zhangde579ab2018-05-25 21:49:49 +0000160 void CheckCompositeFontWidths(const CPDF_Array* widths_array,
Nicolas Penad03ca422017-03-06 13:54:33 -0500161 CPDF_Font* typed_font) {
162 // Check that W array is in a format that conforms to PDF spec 1.7 section
163 // "Glyph Metrics in CIDFonts" (these checks are not
164 // implementation-specific).
Lei Zhangf40380f2018-10-12 18:31:51 +0000165 EXPECT_GT(widths_array->size(), 1u);
Nicolas Penad03ca422017-03-06 13:54:33 -0500166 int num_cids_checked = 0;
167 int cur_cid = 0;
Lei Zhangf40380f2018-10-12 18:31:51 +0000168 for (size_t idx = 0; idx < widths_array->size(); idx++) {
Nicolas Penad03ca422017-03-06 13:54:33 -0500169 int cid = widths_array->GetNumberAt(idx);
170 EXPECT_GE(cid, cur_cid);
Lei Zhangf40380f2018-10-12 18:31:51 +0000171 ASSERT_FALSE(++idx == widths_array->size());
Lei Zhangde579ab2018-05-25 21:49:49 +0000172 const CPDF_Object* next = widths_array->GetObjectAt(idx);
Nicolas Penad03ca422017-03-06 13:54:33 -0500173 if (next->IsArray()) {
174 // We are in the c [w1 w2 ...] case
Lei Zhangde579ab2018-05-25 21:49:49 +0000175 const CPDF_Array* arr = next->AsArray();
Lei Zhangf40380f2018-10-12 18:31:51 +0000176 int cnt = static_cast<int>(arr->size());
Nicolas Penad03ca422017-03-06 13:54:33 -0500177 size_t inner_idx = 0;
178 for (cur_cid = cid; cur_cid < cid + cnt; cur_cid++) {
Lei Zhang70e66192020-09-18 20:50:51 +0000179 int width = arr->GetNumberAt(inner_idx++);
Dan Sinclair971a6742018-03-28 19:23:25 +0000180 EXPECT_EQ(width, typed_font->GetCharWidthF(cur_cid))
181 << " at cid " << cur_cid;
Nicolas Penad03ca422017-03-06 13:54:33 -0500182 }
183 num_cids_checked += cnt;
184 continue;
185 }
186 // Otherwise, are in the c_first c_last w case.
187 ASSERT_TRUE(next->IsNumber());
188 int last_cid = next->AsNumber()->GetInteger();
Lei Zhangf40380f2018-10-12 18:31:51 +0000189 ASSERT_FALSE(++idx == widths_array->size());
Lei Zhang70e66192020-09-18 20:50:51 +0000190 int width = widths_array->GetNumberAt(idx);
Nicolas Penad03ca422017-03-06 13:54:33 -0500191 for (cur_cid = cid; cur_cid <= last_cid; cur_cid++) {
Dan Sinclair971a6742018-03-28 19:23:25 +0000192 EXPECT_EQ(width, typed_font->GetCharWidthF(cur_cid))
193 << " at cid " << cur_cid;
Nicolas Penad03ca422017-03-06 13:54:33 -0500194 }
195 num_cids_checked += last_cid - cid + 1;
196 }
197 // Make sure we have a good amount of cids described
198 EXPECT_GT(num_cids_checked, 900);
199 }
200 CPDF_Document* cpdf_doc() { return cpdf_doc_; }
201
202 private:
203 CPDF_Document* cpdf_doc_;
204};
Tom Sepezd483eb42016-01-06 10:03:59 -0800205
etienneb7712c262016-04-26 08:13:45 -0700206namespace {
thestigdc7ec032016-11-21 15:32:52 -0800207
etienneb7712c262016-04-26 08:13:45 -0700208const char kExpectedPDF[] =
209 "%PDF-1.7\r\n"
210 "%\xA1\xB3\xC5\xD7\r\n"
211 "1 0 obj\r\n"
212 "<</Pages 2 0 R /Type/Catalog>>\r\n"
213 "endobj\r\n"
214 "2 0 obj\r\n"
215 "<</Count 1/Kids\\[ 4 0 R \\]/Type/Pages>>\r\n"
216 "endobj\r\n"
217 "3 0 obj\r\n"
218 "<</CreationDate\\(D:.*\\)/Creator\\(PDFium\\)>>\r\n"
219 "endobj\r\n"
220 "4 0 obj\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400221 "<</MediaBox\\[ 0 0 640 480\\]/Parent 2 0 R "
222 "/Resources<</ExtGState<</FXE1 5 0 R >>>>"
Nicolas Penad9d6c292017-06-06 16:12:10 -0400223 "/Rotate 0/Type/Page"
etienneb7712c262016-04-26 08:13:45 -0700224 ">>\r\n"
225 "endobj\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400226 "5 0 obj\r\n"
227 "<</BM/Normal/CA 1/ca 1>>\r\n"
228 "endobj\r\n"
etienneb7712c262016-04-26 08:13:45 -0700229 "xref\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400230 "0 6\r\n"
etienneb7712c262016-04-26 08:13:45 -0700231 "0000000000 65535 f\r\n"
232 "0000000017 00000 n\r\n"
233 "0000000066 00000 n\r\n"
234 "0000000122 00000 n\r\n"
235 "0000000192 00000 n\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400236 "0000000311 00000 n\r\n"
etienneb7712c262016-04-26 08:13:45 -0700237 "trailer\r\n"
238 "<<\r\n"
239 "/Root 1 0 R\r\n"
240 "/Info 3 0 R\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400241 "/Size 6/ID\\[<.*><.*>\\]>>\r\n"
etienneb7712c262016-04-26 08:13:45 -0700242 "startxref\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400243 "354\r\n"
etienneb7712c262016-04-26 08:13:45 -0700244 "%%EOF\r\n";
thestigdc7ec032016-11-21 15:32:52 -0800245
etienneb7712c262016-04-26 08:13:45 -0700246} // namespace
247
Hui Yingst8e88e382020-11-02 18:19:56 +0000248TEST_F(FPDFEditEmbedderTest, EmbedNotoSansSCFont) {
Lei Zhangb8b4a042021-11-05 00:04:25 +0000249 CreateEmptyDocument();
Hui Yingst8e88e382020-11-02 18:19:56 +0000250 ScopedFPDFPage page(FPDFPage_New(document(), 0, 400, 400));
251 std::string font_path;
Hui Yingst8532ef02020-11-04 19:17:17 +0000252 ASSERT_TRUE(PathService::GetThirdPartyFilePath(
253 "NotoSansCJK/NotoSansSC-Regular.subset.otf", &font_path));
Hui Yingst8e88e382020-11-02 18:19:56 +0000254
255 size_t file_length = 0;
256 std::unique_ptr<char, pdfium::FreeDeleter> font_data =
257 GetFileContents(font_path.c_str(), &file_length);
Lei Zhang786544d2021-07-27 21:25:24 +0000258 ASSERT_TRUE(font_data);
Hui Yingst8e88e382020-11-02 18:19:56 +0000259
260 ScopedFPDFFont font(FPDFText_LoadFont(
261 document(), reinterpret_cast<const uint8_t*>(font_data.get()),
262 file_length, FPDF_FONT_TRUETYPE, /*cid=*/true));
263 FPDF_PAGEOBJECT text_object =
264 FPDFPageObj_CreateTextObj(document(), font.get(), 20.0f);
265 EXPECT_TRUE(text_object);
266
267 // Test the characters which are either mapped to one single unicode or
268 // multiple unicodes in the embedded font.
269 ScopedFPDFWideString text = GetFPDFWideString(L"这是第一句。 这是第二行。");
270 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
271
272 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 50, 200);
273 FPDFPage_InsertObject(page.get(), text_object);
274 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
275
276#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
277#if defined(OS_APPLE)
278 const char kChecksum[] = "9a31fb87d1c6d2346bba22d1196041cd";
Lei Zhang786544d2021-07-27 21:25:24 +0000279#else // defined(OS_APPLE)
Hui Yingst8e88e382020-11-02 18:19:56 +0000280 const char kChecksum[] = "5bb65e15fc0a685934cd5006dec08a76";
281#endif // defined(OS_APPLE)
Lei Zhang786544d2021-07-27 21:25:24 +0000282#else // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingst8e88e382020-11-02 18:19:56 +0000283 const char kChecksum[] = "9a31fb87d1c6d2346bba22d1196041cd";
Hui Yingst8e88e382020-11-02 18:19:56 +0000284#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
285 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
286 CompareBitmap(page_bitmap.get(), 400, 400, kChecksum);
287
Lei Zhang786544d2021-07-27 21:25:24 +0000288 ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
289 VerifySavedDocument(400, 400, kChecksum);
290}
291
292TEST_F(FPDFEditEmbedderTest, EmbedNotoSansSCFontWithCharcodes) {
Lei Zhangb8b4a042021-11-05 00:04:25 +0000293 CreateEmptyDocument();
Lei Zhang786544d2021-07-27 21:25:24 +0000294 ScopedFPDFPage page(FPDFPage_New(document(), 0, 400, 400));
295 std::string font_path;
296 ASSERT_TRUE(PathService::GetThirdPartyFilePath(
297 "NotoSansCJK/NotoSansSC-Regular.subset.otf", &font_path));
298
299 size_t file_length = 0;
300 std::unique_ptr<char, pdfium::FreeDeleter> font_data =
301 GetFileContents(font_path.c_str(), &file_length);
302 ASSERT_TRUE(font_data);
303
304 ScopedFPDFFont font(FPDFText_LoadFont(
305 document(), reinterpret_cast<const uint8_t*>(font_data.get()),
306 file_length, FPDF_FONT_TRUETYPE, /*cid=*/true));
307 FPDF_PAGEOBJECT text_object =
308 FPDFPageObj_CreateTextObj(document(), font.get(), 20.0f);
309 EXPECT_TRUE(text_object);
310
311 // Same as `text` in the EmbedNotoSansSCFont test case above.
312 const std::vector<uint32_t> charcodes = {9, 6, 7, 3, 5, 2, 1,
313 9, 6, 7, 4, 8, 2};
314 EXPECT_TRUE(
315 FPDFText_SetCharcodes(text_object, charcodes.data(), charcodes.size()));
316
317 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 50, 200);
318 FPDFPage_InsertObject(page.get(), text_object);
319 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
320
321#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
322#if defined(OS_APPLE)
323 const char kChecksum[] = "9a31fb87d1c6d2346bba22d1196041cd";
324#else // defined(OS_APPLE)
325 const char kChecksum[] = "5bb65e15fc0a685934cd5006dec08a76";
326#endif // defined(OS_APPLE)
327#else // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Lei Zhang786544d2021-07-27 21:25:24 +0000328 const char kChecksum[] = "9a31fb87d1c6d2346bba22d1196041cd";
Lei Zhang786544d2021-07-27 21:25:24 +0000329#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
330 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
331 CompareBitmap(page_bitmap.get(), 400, 400, kChecksum);
332
333 ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Hui Yingst8e88e382020-11-02 18:19:56 +0000334 VerifySavedDocument(400, 400, kChecksum);
335}
336
Lei Zhangab41f252018-12-23 03:10:50 +0000337TEST_F(FPDFEditEmbedderTest, EmptyCreation) {
Lei Zhangb8b4a042021-11-05 00:04:25 +0000338 CreateEmptyDocument();
weili9b777de2016-08-19 16:19:46 -0700339 FPDF_PAGE page = FPDFPage_New(document(), 0, 640.0, 480.0);
Tom Sepezd483eb42016-01-06 10:03:59 -0800340 EXPECT_NE(nullptr, page);
Nicolas Penad9d6c292017-06-06 16:12:10 -0400341 // The FPDFPage_GenerateContent call should do nothing.
Tom Sepezd483eb42016-01-06 10:03:59 -0800342 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Tom Sepez0aec19b2016-01-07 12:22:44 -0800343 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
etienneb7712c262016-04-26 08:13:45 -0700344
Nicolas Penad9d6c292017-06-06 16:12:10 -0400345 EXPECT_THAT(GetString(), testing::MatchesRegex(std::string(
346 kExpectedPDF, sizeof(kExpectedPDF))));
weili9b777de2016-08-19 16:19:46 -0700347 FPDF_ClosePage(page);
Tom Sepezd483eb42016-01-06 10:03:59 -0800348}
thestigdc7ec032016-11-21 15:32:52 -0800349
350// Regression test for https://crbug.com/667012
Lei Zhangab41f252018-12-23 03:10:50 +0000351TEST_F(FPDFEditEmbedderTest, RasterizePDF) {
thestigdc7ec032016-11-21 15:32:52 -0800352 const char kAllBlackMd5sum[] = "5708fc5c4a8bd0abde99c8e8f0390615";
353
Lei Zhangf0542892019-01-17 18:46:27 +0000354 // Get the bitmap for the original document.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000355 ScopedFPDFBitmap orig_bitmap;
thestigdc7ec032016-11-21 15:32:52 -0800356 {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000357 ASSERT_TRUE(OpenDocument("black.pdf"));
thestigdc7ec032016-11-21 15:32:52 -0800358 FPDF_PAGE orig_page = LoadPage(0);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000359 ASSERT_TRUE(orig_page);
360 orig_bitmap = RenderLoadedPage(orig_page);
361 CompareBitmap(orig_bitmap.get(), 612, 792, kAllBlackMd5sum);
thestigdc7ec032016-11-21 15:32:52 -0800362 UnloadPage(orig_page);
363 }
364
365 // Create a new document from |orig_bitmap| and save it.
366 {
367 FPDF_DOCUMENT temp_doc = FPDF_CreateNewDocument();
368 FPDF_PAGE temp_page = FPDFPage_New(temp_doc, 0, 612, 792);
369
370 // Add the bitmap to an image object and add the image object to the output
371 // page.
Lei Zhangcbd89572017-03-15 17:35:47 -0700372 FPDF_PAGEOBJECT temp_img = FPDFPageObj_NewImageObj(temp_doc);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000373 EXPECT_TRUE(
374 FPDFImageObj_SetBitmap(&temp_page, 1, temp_img, orig_bitmap.get()));
Lei Zhangc8601bf2021-06-29 23:19:27 +0000375 static constexpr FS_MATRIX kLetterScaleMatrix{612, 0, 0, 792, 0, 0};
376 EXPECT_TRUE(FPDFPageObj_SetMatrix(temp_img, &kLetterScaleMatrix));
thestigdc7ec032016-11-21 15:32:52 -0800377 FPDFPage_InsertObject(temp_page, temp_img);
378 EXPECT_TRUE(FPDFPage_GenerateContent(temp_page));
379 EXPECT_TRUE(FPDF_SaveAsCopy(temp_doc, this, 0));
380 FPDF_ClosePage(temp_page);
381 FPDF_CloseDocument(temp_doc);
382 }
thestigdc7ec032016-11-21 15:32:52 -0800383
384 // Get the generated content. Make sure it is at least as big as the original
385 // PDF.
Lei Zhangd72fd582018-07-27 19:37:27 +0000386 EXPECT_GT(GetString().size(), 923u);
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400387 VerifySavedDocument(612, 792, kAllBlackMd5sum);
thestigdc7ec032016-11-21 15:32:52 -0800388}
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500389
Hui Yingsta929df72021-02-26 23:56:18 +0000390TEST_F(FPDFEditEmbedderTest, AddPaths) {
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500391 // Start with a blank page
Nicolas Penad03ca422017-03-06 13:54:33 -0500392 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000393 ASSERT_TRUE(page);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500394
395 // We will first add a red rectangle
396 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000397 ASSERT_TRUE(red_rect);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500398 // Expect false when trying to set colors out of range
Lei Zhang3475b482019-05-13 18:30:57 +0000399 EXPECT_FALSE(FPDFPageObj_SetStrokeColor(red_rect, 100, 100, 100, 300));
400 EXPECT_FALSE(FPDFPageObj_SetFillColor(red_rect, 200, 256, 200, 0));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500401
402 // Fill rectangle with red and insert to the page
Lei Zhang3475b482019-05-13 18:30:57 +0000403 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500404 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
Miklos Vajna491112b2018-05-30 13:30:10 +0000405
406 int fillmode = FPDF_FILLMODE_NONE;
407 FPDF_BOOL stroke = true;
408 EXPECT_TRUE(FPDFPath_GetDrawMode(red_rect, &fillmode, &stroke));
409 EXPECT_EQ(FPDF_FILLMODE_ALTERNATE, fillmode);
410 EXPECT_FALSE(stroke);
411
Lei Zhangc8601bf2021-06-29 23:19:27 +0000412 static constexpr FS_MATRIX kMatrix = {1, 2, 3, 4, 5, 6};
413 EXPECT_TRUE(FPDFPageObj_SetMatrix(red_rect, &kMatrix));
Lei Zhang8da98232019-12-11 23:29:33 +0000414
415 FS_MATRIX matrix;
Lei Zhangc8601bf2021-06-29 23:19:27 +0000416 EXPECT_TRUE(FPDFPageObj_GetMatrix(red_rect, &matrix));
Lei Zhang8da98232019-12-11 23:29:33 +0000417 EXPECT_FLOAT_EQ(1.0f, matrix.a);
418 EXPECT_FLOAT_EQ(2.0f, matrix.b);
419 EXPECT_FLOAT_EQ(3.0f, matrix.c);
420 EXPECT_FLOAT_EQ(4.0f, matrix.d);
421 EXPECT_FLOAT_EQ(5.0f, matrix.e);
422 EXPECT_FLOAT_EQ(6.0f, matrix.f);
423
424 // Set back the identity matrix.
425 matrix = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
Lei Zhangc8601bf2021-06-29 23:19:27 +0000426 EXPECT_TRUE(FPDFPageObj_SetMatrix(red_rect, &matrix));
Miklos Vajna97f4d672018-06-04 14:47:17 +0000427
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500428 FPDFPage_InsertObject(page, red_rect);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000429 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000430 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +0000431 CompareBitmap(page_bitmap.get(), 612, 792, kRedRectangleChecksum);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000432 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500433
434 // Now add to that a green rectangle with some medium alpha
435 FPDF_PAGEOBJECT green_rect = FPDFPageObj_CreateNewRect(100, 100, 40, 40);
Lei Zhang3475b482019-05-13 18:30:57 +0000436 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_rect, 0, 255, 0, 128));
Miklos Vajnaed4705b2017-04-05 09:24:50 +0200437
Miklos Vajna1ef04c92017-05-08 18:14:19 +0200438 // Make sure the type of the rectangle is a path.
439 EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(green_rect));
440
Miklos Vajnaed4705b2017-04-05 09:24:50 +0200441 // Make sure we get back the same color we set previously.
442 unsigned int R;
443 unsigned int G;
444 unsigned int B;
445 unsigned int A;
Lei Zhang3475b482019-05-13 18:30:57 +0000446 EXPECT_TRUE(FPDFPageObj_GetFillColor(green_rect, &R, &G, &B, &A));
Lei Zhangd72fd582018-07-27 19:37:27 +0000447 EXPECT_EQ(0u, R);
448 EXPECT_EQ(255u, G);
449 EXPECT_EQ(0u, B);
450 EXPECT_EQ(128u, A);
Miklos Vajnaed4705b2017-04-05 09:24:50 +0200451
Lei Zhang9b4b8df2021-06-12 06:38:48 +0000452 // Make sure the path has 5 points (1 CFX_Path::Point::Type::kMove and 4
453 // CFX_Path::Point::Type::kLine).
Miklos Vajna0150a542017-09-21 21:46:56 +0200454 ASSERT_EQ(5, FPDFPath_CountSegments(green_rect));
Miklos Vajna36eed872017-09-20 22:52:43 +0200455 // Verify actual coordinates.
456 FPDF_PATHSEGMENT segment = FPDFPath_GetPathSegment(green_rect, 0);
457 float x;
458 float y;
459 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
460 EXPECT_EQ(100, x);
461 EXPECT_EQ(100, y);
462 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
463 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
464 segment = FPDFPath_GetPathSegment(green_rect, 1);
465 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
466 EXPECT_EQ(100, x);
467 EXPECT_EQ(140, y);
468 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
469 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
470 segment = FPDFPath_GetPathSegment(green_rect, 2);
471 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
472 EXPECT_EQ(140, x);
473 EXPECT_EQ(140, y);
474 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
475 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
476 segment = FPDFPath_GetPathSegment(green_rect, 3);
477 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
478 EXPECT_EQ(140, x);
479 EXPECT_EQ(100, y);
480 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
481 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
482 segment = FPDFPath_GetPathSegment(green_rect, 4);
483 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
484 EXPECT_EQ(100, x);
485 EXPECT_EQ(100, y);
486 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
487 EXPECT_TRUE(FPDFPathSegment_GetClose(segment));
Miklos Vajna12abfd02017-09-15 07:49:03 +0200488
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500489 EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect, FPDF_FILLMODE_WINDING, 0));
490 FPDFPage_InsertObject(page, green_rect);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000491 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000492 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000493 CompareBitmap(page_bitmap.get(), 612, 792,
494 "7b0b87604594e773add528fae567a558");
495 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500496
497 // Add a black triangle.
498 FPDF_PAGEOBJECT black_path = FPDFPageObj_CreateNewPath(400, 100);
Lei Zhang3475b482019-05-13 18:30:57 +0000499 EXPECT_TRUE(FPDFPageObj_SetFillColor(black_path, 0, 0, 0, 200));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500500 EXPECT_TRUE(FPDFPath_SetDrawMode(black_path, FPDF_FILLMODE_ALTERNATE, 0));
501 EXPECT_TRUE(FPDFPath_LineTo(black_path, 400, 200));
502 EXPECT_TRUE(FPDFPath_LineTo(black_path, 300, 100));
503 EXPECT_TRUE(FPDFPath_Close(black_path));
Miklos Vajna12abfd02017-09-15 07:49:03 +0200504
Lei Zhang9b4b8df2021-06-12 06:38:48 +0000505 // Make sure the path has 3 points (1 CFX_Path::Point::Type::kMove and 2
506 // CFX_Path::Point::Type::kLine).
Miklos Vajna0150a542017-09-21 21:46:56 +0200507 ASSERT_EQ(3, FPDFPath_CountSegments(black_path));
Miklos Vajna36eed872017-09-20 22:52:43 +0200508 // Verify actual coordinates.
509 segment = FPDFPath_GetPathSegment(black_path, 0);
510 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
511 EXPECT_EQ(400, x);
512 EXPECT_EQ(100, y);
513 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
514 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
515 segment = FPDFPath_GetPathSegment(black_path, 1);
516 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
517 EXPECT_EQ(400, x);
518 EXPECT_EQ(200, y);
519 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
520 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
521 segment = FPDFPath_GetPathSegment(black_path, 2);
522 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
523 EXPECT_EQ(300, x);
524 EXPECT_EQ(100, y);
525 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
526 EXPECT_TRUE(FPDFPathSegment_GetClose(segment));
527 // Make sure out of bounds index access fails properly.
528 EXPECT_EQ(nullptr, FPDFPath_GetPathSegment(black_path, 3));
Miklos Vajna12abfd02017-09-15 07:49:03 +0200529
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500530 FPDFPage_InsertObject(page, black_path);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000531 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000532 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000533 CompareBitmap(page_bitmap.get(), 612, 792,
534 "eadc8020a14dfcf091da2688733d8806");
535 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500536
537 // Now add a more complex blue path.
538 FPDF_PAGEOBJECT blue_path = FPDFPageObj_CreateNewPath(200, 200);
Lei Zhang3475b482019-05-13 18:30:57 +0000539 EXPECT_TRUE(FPDFPageObj_SetFillColor(blue_path, 0, 0, 255, 255));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500540 EXPECT_TRUE(FPDFPath_SetDrawMode(blue_path, FPDF_FILLMODE_WINDING, 0));
541 EXPECT_TRUE(FPDFPath_LineTo(blue_path, 230, 230));
542 EXPECT_TRUE(FPDFPath_BezierTo(blue_path, 250, 250, 280, 280, 300, 300));
543 EXPECT_TRUE(FPDFPath_LineTo(blue_path, 325, 325));
544 EXPECT_TRUE(FPDFPath_LineTo(blue_path, 350, 325));
545 EXPECT_TRUE(FPDFPath_BezierTo(blue_path, 375, 330, 390, 360, 400, 400));
546 EXPECT_TRUE(FPDFPath_Close(blue_path));
547 FPDFPage_InsertObject(page, blue_path);
Hui Yingsta929df72021-02-26 23:56:18 +0000548#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
549 static constexpr char kLastChecksum[] = "ed14c60702b1489c597c7d46ece7f86d";
550#else
551 static constexpr char kLastChecksum[] = "9823e1a21bd9b72b6a442ba4f12af946";
552#endif
Lei Zhang107fa7b2018-02-09 21:48:15 +0000553 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000554 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingsta929df72021-02-26 23:56:18 +0000555 CompareBitmap(page_bitmap.get(), 612, 792, kLastChecksum);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000556 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500557
558 // Now save the result, closing the page and document
Nicolas Pena207b7272017-05-26 17:37:06 -0400559 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Nicolas Penad03ca422017-03-06 13:54:33 -0500560 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500561 FPDF_ClosePage(page);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500562
563 // Render the saved result
Hui Yingsta929df72021-02-26 23:56:18 +0000564 VerifySavedDocument(612, 792, kLastChecksum);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500565}
566
Miklos Vajna45501f32019-07-30 07:41:02 +0000567TEST_F(FPDFEditEmbedderTest, ClipPath) {
568 // Load document with a clipped rectangle.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000569 ASSERT_TRUE(OpenDocument("clip_path.pdf"));
Miklos Vajna45501f32019-07-30 07:41:02 +0000570 FPDF_PAGE page = LoadPage(0);
571 ASSERT_TRUE(page);
572
573 ASSERT_EQ(1, FPDFPage_CountObjects(page));
574
575 FPDF_PAGEOBJECT triangle = FPDFPage_GetObject(page, 0);
576 ASSERT_TRUE(triangle);
577
578 // Test that we got the expected triangle.
579 ASSERT_EQ(4, FPDFPath_CountSegments(triangle));
580
581 FPDF_PATHSEGMENT segment = FPDFPath_GetPathSegment(triangle, 0);
582 float x;
583 float y;
584 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
585 EXPECT_EQ(10, x);
586 EXPECT_EQ(10, y);
587 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
588 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
589
590 segment = FPDFPath_GetPathSegment(triangle, 1);
591 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
592 EXPECT_EQ(25, x);
593 EXPECT_EQ(40, y);
594 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
595 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
596
597 segment = FPDFPath_GetPathSegment(triangle, 2);
598 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
599 EXPECT_EQ(40, x);
600 EXPECT_EQ(10, y);
601 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
602 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
603
604 segment = FPDFPath_GetPathSegment(triangle, 3);
605 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
606 EXPECT_TRUE(FPDFPathSegment_GetClose(segment));
607
608 // Test FPDFPageObj_GetClipPath().
609 ASSERT_EQ(nullptr, FPDFPageObj_GetClipPath(nullptr));
610
611 FPDF_CLIPPATH clip_path = FPDFPageObj_GetClipPath(triangle);
612 ASSERT_TRUE(clip_path);
613
614 // Test FPDFClipPath_CountPaths().
615 ASSERT_EQ(-1, FPDFClipPath_CountPaths(nullptr));
616 ASSERT_EQ(1, FPDFClipPath_CountPaths(clip_path));
617
618 // Test FPDFClipPath_CountPathSegments().
619 ASSERT_EQ(-1, FPDFClipPath_CountPathSegments(nullptr, 0));
620 ASSERT_EQ(-1, FPDFClipPath_CountPathSegments(clip_path, -1));
621 ASSERT_EQ(-1, FPDFClipPath_CountPathSegments(clip_path, 1));
622 ASSERT_EQ(4, FPDFClipPath_CountPathSegments(clip_path, 0));
623
624 // FPDFClipPath_GetPathSegment() negative testing.
625 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(nullptr, 0, 0));
626 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, -1, 0));
627 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, 1, 0));
628 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, 0, -1));
629 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, 0, 4));
630
631 // FPDFClipPath_GetPathSegment() positive testing.
632 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 0);
633 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
634 EXPECT_EQ(10, x);
635 EXPECT_EQ(15, y);
636 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
637 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
638
639 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 1);
640 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
641 EXPECT_EQ(40, x);
642 EXPECT_EQ(15, y);
643 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
644 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
645
646 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 2);
647 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
648 EXPECT_EQ(40, x);
649 EXPECT_EQ(35, y);
650 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
651 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
652
653 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 3);
654 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
655 EXPECT_EQ(10, x);
656 EXPECT_EQ(35, y);
657 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
658 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
659
660 UnloadPage(page);
661}
662
Lei Zhang571f9322019-09-25 12:40:25 +0000663TEST_F(FPDFEditEmbedderTest, BUG_1399) {
664 // Load document with a clipped rectangle.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000665 ASSERT_TRUE(OpenDocument("bug_1399.pdf"));
Lei Zhang571f9322019-09-25 12:40:25 +0000666 FPDF_PAGE page = LoadPage(0);
667 ASSERT_TRUE(page);
668
669 ASSERT_EQ(7, FPDFPage_CountObjects(page));
670
671 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
672 ASSERT_TRUE(obj);
673
674 ASSERT_EQ(2, FPDFPath_CountSegments(obj));
675
676 FPDF_PATHSEGMENT segment = FPDFPath_GetPathSegment(obj, 0);
677 float x;
678 float y;
679 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
680 EXPECT_FLOAT_EQ(107.718f, x);
681 EXPECT_FLOAT_EQ(719.922f, y);
682 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
683 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
684
685 segment = FPDFPath_GetPathSegment(obj, 1);
686 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
687 EXPECT_FLOAT_EQ(394.718f, x);
688 EXPECT_FLOAT_EQ(719.922f, y);
689 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
690 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
691
692 FPDF_CLIPPATH clip_path = FPDFPageObj_GetClipPath(obj);
693 ASSERT_TRUE(clip_path);
694
695 EXPECT_EQ(-1, FPDFClipPath_CountPaths(clip_path));
696 EXPECT_EQ(-1, FPDFClipPath_CountPathSegments(clip_path, 0));
697 EXPECT_FALSE(FPDFClipPath_GetPathSegment(clip_path, 0, 0));
698
699 UnloadPage(page);
700}
701
Lei Zhangfcf7e7f2021-07-02 18:46:54 +0000702TEST_F(FPDFEditEmbedderTest, BUG_1549) {
703 static const char kOriginalChecksum[] = "126366fb95e6caf8ea196780075b22b2";
704 static const char kRemovedChecksum[] = "6ec2f27531927882624b37bc7d8e12f4";
705
706 ASSERT_TRUE(OpenDocument("bug_1549.pdf"));
707 FPDF_PAGE page = LoadPage(0);
708
709 {
710 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
711 CompareBitmap(bitmap.get(), 100, 150, kOriginalChecksum);
712
713 ScopedFPDFPageObject obj(FPDFPage_GetObject(page, 0));
714 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj.get()));
715 ASSERT_TRUE(FPDFPage_RemoveObject(page, obj.get()));
716 }
717
718 ASSERT_TRUE(FPDFPage_GenerateContent(page));
719
720 {
721 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
722 CompareBitmap(bitmap.get(), 100, 150, kRemovedChecksum);
723 }
724
725 ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
726 UnloadPage(page);
727
728 // TODO(crbug.com/pdfium/1549): Should be `kRemovedChecksum`.
729 VerifySavedDocument(100, 150, "4f9889cd5993db20f1ab37d677ac8d26");
730}
731
Hui Yingstcb4203d2020-06-09 01:48:47 +0000732TEST_F(FPDFEditEmbedderTest, SetText) {
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000733 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000734 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000735 FPDF_PAGE page = LoadPage(0);
736 ASSERT_TRUE(page);
737
738 // Get the "Hello, world!" text object and change it.
739 ASSERT_EQ(2, FPDFPage_CountObjects(page));
740 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
741 ASSERT_TRUE(page_object);
Lei Zhangf0f67682019-04-08 17:03:21 +0000742 ScopedFPDFWideString text1 = GetFPDFWideString(L"Changed for SetText test");
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000743 EXPECT_TRUE(FPDFText_SetText(page_object, text1.get()));
744
745 // Verify the "Hello, world!" text is gone and "Changed for SetText test" is
746 // now displayed.
747 ASSERT_EQ(2, FPDFPage_CountObjects(page));
Hui Yingstcb4203d2020-06-09 01:48:47 +0000748
749#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingstcb4203d2020-06-09 01:48:47 +0000750 const char kChangedChecksum[] = "6bc5171f4eb329474989c6ccfa3d6303";
Hui Yingstcb4203d2020-06-09 01:48:47 +0000751#else
752#if defined(OS_WIN)
753 const char kChangedChecksum[] = "3137fdb27962671f5c3963a5e965eff5";
Lei Zhang0c03d632020-07-30 17:05:36 +0000754#elif defined(OS_APPLE)
Hui Yingstcb4203d2020-06-09 01:48:47 +0000755 const char kChangedChecksum[] = "904132275a1144ea06b0694537c80b4c";
756#else
757 const char kChangedChecksum[] = "a0c4ea6620772991f66bf7130379b08a";
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000758#endif
Hui Yingstcb4203d2020-06-09 01:48:47 +0000759#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000760 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000761 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstcb4203d2020-06-09 01:48:47 +0000762 CompareBitmap(page_bitmap.get(), 200, 200, kChangedChecksum);
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000763 }
764
765 // Now save the result.
766 EXPECT_TRUE(FPDFPage_GenerateContent(page));
767 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
768
769 UnloadPage(page);
770
771 // Re-open the file and check the changes were kept in the saved .pdf.
Lei Zhang0b494052019-01-31 21:41:15 +0000772 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000773 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +0000774 ASSERT_TRUE(saved_page);
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000775 EXPECT_EQ(2, FPDFPage_CountObjects(saved_page));
776 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000777 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstcb4203d2020-06-09 01:48:47 +0000778 CompareBitmap(page_bitmap.get(), 200, 200, kChangedChecksum);
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000779 }
780
781 CloseSavedPage(saved_page);
782 CloseSavedDocument();
783}
784
Lei Zhang786544d2021-07-27 21:25:24 +0000785TEST_F(FPDFEditEmbedderTest, SetCharcodesBadParams) {
786 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
787 FPDF_PAGE page = LoadPage(0);
788 ASSERT_TRUE(page);
789
790 ASSERT_EQ(2, FPDFPage_CountObjects(page));
791 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
792 ASSERT_TRUE(page_object);
793
794 const uint32_t kDummyValue = 42;
795 EXPECT_FALSE(FPDFText_SetCharcodes(nullptr, nullptr, 0));
796 EXPECT_FALSE(FPDFText_SetCharcodes(nullptr, nullptr, 1));
797 EXPECT_FALSE(FPDFText_SetCharcodes(nullptr, &kDummyValue, 0));
798 EXPECT_FALSE(FPDFText_SetCharcodes(nullptr, &kDummyValue, 1));
799 EXPECT_FALSE(FPDFText_SetCharcodes(page_object, nullptr, 1));
800
801 UnloadPage(page);
802}
803
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000804TEST_F(FPDFEditEmbedderTest, SetTextKeepClippingPath) {
Daniel Hosseinianda651442020-07-17 23:30:22 +0000805 // Load document with some text, with parts clipped.
806 ASSERT_TRUE(OpenDocument("bug_1558.pdf"));
807 FPDF_PAGE page = LoadPage(0);
808 ASSERT_TRUE(page);
809
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000810#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Daniel Hosseinianda651442020-07-17 23:30:22 +0000811 static constexpr char kOriginalChecksum[] =
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000812 "1e08d555f4863ff34a90f849c9464ed2";
813#else
Daniel Hosseinianda651442020-07-17 23:30:22 +0000814#if defined(OS_WIN)
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000815 static constexpr char kOriginalChecksum[] =
Daniel Hosseinianda651442020-07-17 23:30:22 +0000816 "220bf2086398fc46ac094952b244c8d9";
Lei Zhang0c03d632020-07-30 17:05:36 +0000817#elif defined(OS_APPLE)
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000818 static constexpr char kOriginalChecksum[] =
Daniel Hosseinianda651442020-07-17 23:30:22 +0000819 "53cbaad93551ef2ccc27ddd63f2ca2b3";
820#else
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000821 static constexpr char kOriginalChecksum[] =
Daniel Hosseinianda651442020-07-17 23:30:22 +0000822 "ba1936fa8ca1e8cca108da76ff3500a6";
823#endif
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000824#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Daniel Hosseinianda651442020-07-17 23:30:22 +0000825 {
826 // When opened before any editing and saving, the clipping path is rendered.
827 ScopedFPDFBitmap original_bitmap = RenderPage(page);
828 CompareBitmap(original_bitmap.get(), 200, 200, kOriginalChecksum);
829 }
830
831 // "Change" the text in the objects to their current values to force them to
832 // regenerate when saving.
833 {
834 ScopedFPDFTextPage text_page(FPDFText_LoadPage(page));
835 ASSERT_TRUE(text_page);
836 const int obj_count = FPDFPage_CountObjects(page);
837 ASSERT_EQ(2, obj_count);
838 for (int i = 0; i < obj_count; ++i) {
839 FPDF_PAGEOBJECT text_obj = FPDFPage_GetObject(page, i);
840 ASSERT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(text_obj));
841 unsigned long size =
842 FPDFTextObj_GetText(text_obj, text_page.get(),
843 /*buffer=*/nullptr, /*length=*/0);
844 ASSERT_GT(size, 0u);
845 std::vector<FPDF_WCHAR> buffer = GetFPDFWideStringBuffer(size);
846 ASSERT_EQ(size, FPDFTextObj_GetText(text_obj, text_page.get(),
847 buffer.data(), size));
848 EXPECT_TRUE(FPDFText_SetText(text_obj, buffer.data()));
849 }
850 }
851
852 {
853 // After editing but before saving, the clipping path is retained.
854 ScopedFPDFBitmap edited_bitmap = RenderPage(page);
855 CompareBitmap(edited_bitmap.get(), 200, 200, kOriginalChecksum);
856 }
857
858 // Save the file.
859 EXPECT_TRUE(FPDFPage_GenerateContent(page));
860 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
861 UnloadPage(page);
862
863 // Open the saved copy and render it.
864 ASSERT_TRUE(OpenSavedDocument());
865 FPDF_PAGE saved_page = LoadSavedPage(0);
866 ASSERT_TRUE(saved_page);
867
868 {
Daniel Hosseinianda651442020-07-17 23:30:22 +0000869 ScopedFPDFBitmap saved_bitmap = RenderSavedPage(saved_page);
Daniel Hosseinian75efd912020-07-21 08:07:28 +0000870 CompareBitmap(saved_bitmap.get(), 200, 200, kOriginalChecksum);
Daniel Hosseinianda651442020-07-17 23:30:22 +0000871 }
872
873 CloseSavedPage(saved_page);
874 CloseSavedDocument();
875}
876
Daniel Hosseinian7b819bf2021-01-27 19:40:34 +0000877TEST_F(FPDFEditEmbedderTest, BUG_1574) {
878 // Load document with some text within a clipping path.
879 ASSERT_TRUE(OpenDocument("bug_1574.pdf"));
880 FPDF_PAGE page = LoadPage(0);
881 ASSERT_TRUE(page);
882
883#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
884 static constexpr char kOriginalChecksum[] =
885 "c17ce567e0fd2ecd14352cf56d8d574b";
886#else
887#if defined(OS_WIN)
888 static constexpr char kOriginalChecksum[] =
889 "297c5e52c38802106d570e35f94b5cfd";
890#elif defined(OS_APPLE)
891 static constexpr char kOriginalChecksum[] =
892 "6a11148c99a141eea7c2b91e6987eb97";
893#else
894 static constexpr char kOriginalChecksum[] =
895 "75b6f6da7c24f2e395edb1c7d81dc906";
896#endif
897#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
898 {
899 // When opened before any editing and saving, the text object is rendered.
900 ScopedFPDFBitmap original_bitmap = RenderPage(page);
901 CompareBitmap(original_bitmap.get(), 200, 300, kOriginalChecksum);
902 }
903
904 // "Change" the text in the objects to their current values to force them to
905 // regenerate when saving.
906 {
907 ScopedFPDFTextPage text_page(FPDFText_LoadPage(page));
908 ASSERT_TRUE(text_page);
909
910 ASSERT_EQ(2, FPDFPage_CountObjects(page));
911 FPDF_PAGEOBJECT text_obj = FPDFPage_GetObject(page, 1);
912 ASSERT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(text_obj));
913
914 unsigned long size = FPDFTextObj_GetText(text_obj, text_page.get(),
915 /*buffer=*/nullptr, /*length=*/0);
916 ASSERT_GT(size, 0u);
917 std::vector<FPDF_WCHAR> buffer = GetFPDFWideStringBuffer(size);
918 ASSERT_EQ(size, FPDFTextObj_GetText(text_obj, text_page.get(),
919 buffer.data(), size));
920 EXPECT_TRUE(FPDFText_SetText(text_obj, buffer.data()));
921 }
922
923 // Save the file.
924 EXPECT_TRUE(FPDFPage_GenerateContent(page));
925 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
926 UnloadPage(page);
927
928 // Open the saved copy and render it.
929 ASSERT_TRUE(OpenSavedDocument());
930 FPDF_PAGE saved_page = LoadSavedPage(0);
931 ASSERT_TRUE(saved_page);
932
Daniel Hosseinian7b819bf2021-01-27 19:40:34 +0000933 {
934 ScopedFPDFBitmap saved_bitmap = RenderSavedPage(saved_page);
Daniel Hosseinian91eeeb92021-01-27 19:53:24 +0000935 CompareBitmap(saved_bitmap.get(), 200, 300, kOriginalChecksum);
Daniel Hosseinian7b819bf2021-01-27 19:40:34 +0000936 }
937
938 CloseSavedPage(saved_page);
939 CloseSavedDocument();
940}
941
Hui Yingst08c40712020-04-29 01:37:35 +0000942TEST_F(FPDFEditEmbedderTest, RemovePageObject) {
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000943 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000944 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000945 FPDF_PAGE page = LoadPage(0);
946 ASSERT_TRUE(page);
947
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000948 // Show what the original file looks like.
949 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000950 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +0000951 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000952 }
953
954 // Get the "Hello, world!" text object and remove it.
955 ASSERT_EQ(2, FPDFPage_CountObjects(page));
956 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
957 ASSERT_TRUE(page_object);
958 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
959
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000960 // Verify the "Hello, world!" text is gone.
961 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000962 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +0000963 CompareBitmap(page_bitmap.get(), 200, 200, kFirstRemovedChecksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000964 }
965 ASSERT_EQ(1, FPDFPage_CountObjects(page));
966
967 UnloadPage(page);
968 FPDFPageObj_Destroy(page_object);
969}
970
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000971void CheckMarkCounts(FPDF_PAGE page,
972 int start_from,
973 int expected_object_count,
974 size_t expected_prime_count,
975 size_t expected_square_count,
976 size_t expected_greater_than_ten_count,
977 size_t expected_bounds_count) {
978 int object_count = FPDFPage_CountObjects(page);
979 ASSERT_EQ(expected_object_count, object_count);
980
981 size_t prime_count = 0;
982 size_t square_count = 0;
983 size_t greater_than_ten_count = 0;
984 size_t bounds_count = 0;
985 for (int i = 0; i < object_count; ++i) {
986 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
987
988 int mark_count = FPDFPageObj_CountMarks(page_object);
989 for (int j = 0; j < mark_count; ++j) {
990 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
991
992 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +0000993 unsigned long name_len = 999u;
994 ASSERT_TRUE(
995 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
996 EXPECT_GT(name_len, 0u);
997 EXPECT_NE(999u, name_len);
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000998 std::wstring name =
999 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1000 if (name == L"Prime") {
1001 prime_count++;
1002 } else if (name == L"Square") {
1003 square_count++;
1004 int expected_square = start_from + i;
1005 EXPECT_EQ(1, FPDFPageObjMark_CountParams(mark));
1006
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001007 unsigned long get_param_key_return = 999u;
1008 ASSERT_TRUE(FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer),
1009 &get_param_key_return));
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001010 EXPECT_EQ((6u + 1u) * 2u, get_param_key_return);
1011 std::wstring key =
1012 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1013 EXPECT_EQ(L"Factor", key);
1014
1015 EXPECT_EQ(FPDF_OBJECT_NUMBER,
Henrique Nakashima94230e52018-07-11 22:02:02 +00001016 FPDFPageObjMark_GetParamValueType(mark, "Factor"));
Henrique Nakashima140dead2018-07-11 21:40:03 +00001017 int square_root;
Henrique Nakashima94230e52018-07-11 22:02:02 +00001018 EXPECT_TRUE(
1019 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &square_root));
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001020 EXPECT_EQ(expected_square, square_root * square_root);
1021 } else if (name == L"GreaterThanTen") {
1022 greater_than_ten_count++;
1023 } else if (name == L"Bounds") {
1024 bounds_count++;
1025 EXPECT_EQ(1, FPDFPageObjMark_CountParams(mark));
1026
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001027 unsigned long get_param_key_return = 999u;
1028 ASSERT_TRUE(FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer),
1029 &get_param_key_return));
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001030 EXPECT_EQ((8u + 1u) * 2u, get_param_key_return);
1031 std::wstring key =
1032 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1033 EXPECT_EQ(L"Position", key);
1034
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001035 EXPECT_EQ(FPDF_OBJECT_STRING,
Henrique Nakashima94230e52018-07-11 22:02:02 +00001036 FPDFPageObjMark_GetParamValueType(mark, "Position"));
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001037 unsigned long length;
Henrique Nakashimaa3406772018-07-13 19:10:53 +00001038 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
1039 mark, "Position", buffer, sizeof(buffer), &length));
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001040 ASSERT_GT(length, 0u);
Henrique Nakashima140dead2018-07-11 21:40:03 +00001041 std::wstring value =
1042 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00001043
Henrique Nakashimaa3406772018-07-13 19:10:53 +00001044 // "Position" can be "First", "Last", or "End".
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00001045 if (i == 0) {
1046 EXPECT_EQ((5u + 1u) * 2u, length);
1047 EXPECT_EQ(L"First", value);
1048 } else if (i == object_count - 1) {
Henrique Nakashimaa3406772018-07-13 19:10:53 +00001049 if (length == (4u + 1u) * 2u) {
1050 EXPECT_EQ(L"Last", value);
1051 } else if (length == (3u + 1u) * 2u) {
1052 EXPECT_EQ(L"End", value);
1053 } else {
1054 FAIL();
1055 }
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00001056 } else {
1057 FAIL();
1058 }
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001059 } else {
1060 FAIL();
1061 }
1062 }
1063 }
1064
1065 // Expect certain number of tagged objects. The test file contains strings
1066 // from 1 to 19.
1067 EXPECT_EQ(expected_prime_count, prime_count);
1068 EXPECT_EQ(expected_square_count, square_count);
1069 EXPECT_EQ(expected_greater_than_ten_count, greater_than_ten_count);
1070 EXPECT_EQ(expected_bounds_count, bounds_count);
1071}
1072
Lei Zhangab41f252018-12-23 03:10:50 +00001073TEST_F(FPDFEditEmbedderTest, ReadMarkedObjectsIndirectDict) {
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001074 // Load document with some text marked with an indirect property.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001075 ASSERT_TRUE(OpenDocument("text_in_page_marked_indirect.pdf"));
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001076 FPDF_PAGE page = LoadPage(0);
1077 ASSERT_TRUE(page);
1078
1079 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
1080
1081 UnloadPage(page);
1082}
1083
Hui Yingstf26b5f82020-11-17 05:26:03 +00001084TEST_F(FPDFEditEmbedderTest, RemoveMarkedObjectsPrime) {
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001085 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001086 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001087 FPDF_PAGE page = LoadPage(0);
1088 ASSERT_TRUE(page);
1089
1090 // Show what the original file looks like.
1091 {
Hui Yingstf26b5f82020-11-17 05:26:03 +00001092#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1093 static constexpr char kOriginalChecksum[] =
1094 "748ed321a485d246ca6260b9e30dd200";
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001095#else
Hui Yingst282f0b82021-08-30 22:59:52 +00001096#if defined(OS_APPLE)
Hui Yingstf26b5f82020-11-17 05:26:03 +00001097 static constexpr char kOriginalChecksum[] =
1098 "adf815e53c788a5272b4df07c610a1da";
1099#else
1100 static constexpr char kOriginalChecksum[] =
1101 "41647268d5911d049801803b15c2dfb0";
Hui Yingst282f0b82021-08-30 22:59:52 +00001102#endif // defined(OS_APPLE)
Hui Yingstf26b5f82020-11-17 05:26:03 +00001103#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Lei Zhang30ff2532019-01-31 21:37:55 +00001104 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstf26b5f82020-11-17 05:26:03 +00001105 CompareBitmap(page_bitmap.get(), 200, 200, kOriginalChecksum);
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001106 }
1107
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001108 constexpr int expected_object_count = 19;
1109 CheckMarkCounts(page, 1, expected_object_count, 8, 4, 9, 1);
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001110
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001111 // Get all objects marked with "Prime"
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001112 std::vector<FPDF_PAGEOBJECT> primes;
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001113 for (int i = 0; i < expected_object_count; ++i) {
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001114 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1115
1116 int mark_count = FPDFPageObj_CountMarks(page_object);
1117 for (int j = 0; j < mark_count; ++j) {
1118 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
1119
1120 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001121 unsigned long name_len = 999u;
1122 ASSERT_TRUE(
1123 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
1124 EXPECT_GT(name_len, 0u);
1125 EXPECT_NE(999u, name_len);
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001126 std::wstring name =
1127 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1128 if (name == L"Prime") {
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001129 primes.push_back(page_object);
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001130 }
1131 }
1132 }
1133
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001134 // Remove all objects marked with "Prime".
1135 for (FPDF_PAGEOBJECT page_object : primes) {
1136 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1137 FPDFPageObj_Destroy(page_object);
1138 }
1139
1140 EXPECT_EQ(11, FPDFPage_CountObjects(page));
Hui Yingstf26b5f82020-11-17 05:26:03 +00001141#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1142 static constexpr char kNonPrimesChecksum[] =
1143 "e2927fe2b7bbb595aca2a0e19ef3f1e8";
1144 static constexpr char kNonPrimesAfterSaveChecksum[] =
1145 "e2927fe2b7bbb595aca2a0e19ef3f1e8";
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001146#else
Hui Yingst282f0b82021-08-30 22:59:52 +00001147#if defined(OS_APPLE)
Hui Yingstf26b5f82020-11-17 05:26:03 +00001148 static constexpr char kNonPrimesChecksum[] =
1149 "d29e2ddff56e0d12f340794d26796400";
1150 static constexpr char kNonPrimesAfterSaveChecksum[] =
1151 "10eff2cd0037b661496981779601fa6f";
1152#else
1153 static constexpr char kNonPrimesChecksum[] =
1154 "67ab13115d0cc34e99a1003c28047b40";
1155 static constexpr char kNonPrimesAfterSaveChecksum[] =
1156 "67ab13115d0cc34e99a1003c28047b40";
Hui Yingst282f0b82021-08-30 22:59:52 +00001157#endif // defined(OS_APPLE)
Hui Yingstf26b5f82020-11-17 05:26:03 +00001158#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001159 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001160 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstf26b5f82020-11-17 05:26:03 +00001161 CompareBitmap(page_bitmap.get(), 200, 200, kNonPrimesChecksum);
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001162 }
1163
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001164 // Save the file.
1165 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1166 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001167 UnloadPage(page);
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001168
1169 // Re-open the file and check the prime marks are not there anymore.
Lei Zhang0b494052019-01-31 21:41:15 +00001170 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001171 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001172 ASSERT_TRUE(saved_page);
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001173 EXPECT_EQ(11, FPDFPage_CountObjects(saved_page));
1174
1175 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001176 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstf26b5f82020-11-17 05:26:03 +00001177 CompareBitmap(page_bitmap.get(), 200, 200, kNonPrimesAfterSaveChecksum);
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001178 }
1179
1180 CloseSavedPage(saved_page);
1181 CloseSavedDocument();
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001182}
1183
Lei Zhangab41f252018-12-23 03:10:50 +00001184TEST_F(FPDFEditEmbedderTest, RemoveMarks) {
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001185 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001186 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001187 FPDF_PAGE page = LoadPage(0);
1188 ASSERT_TRUE(page);
1189
1190 constexpr int kExpectedObjectCount = 19;
1191 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
1192
1193 // Remove all "Prime" content marks.
1194 for (int i = 0; i < kExpectedObjectCount; ++i) {
1195 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1196
1197 int mark_count = FPDFPageObj_CountMarks(page_object);
1198 for (int j = mark_count - 1; j >= 0; --j) {
1199 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
1200
1201 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001202 unsigned long name_len = 999u;
1203 ASSERT_TRUE(
1204 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
1205 EXPECT_GT(name_len, 0u);
1206 EXPECT_NE(999u, name_len);
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001207 std::wstring name =
1208 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1209 if (name == L"Prime") {
1210 // Remove mark.
1211 EXPECT_TRUE(FPDFPageObj_RemoveMark(page_object, mark));
1212
1213 // Verify there is now one fewer mark in the page object.
1214 EXPECT_EQ(mark_count - 1, FPDFPageObj_CountMarks(page_object));
1215 }
1216 }
1217 }
1218
1219 // Verify there are 0 "Prime" content marks now.
1220 CheckMarkCounts(page, 1, kExpectedObjectCount, 0, 4, 9, 1);
1221
1222 // Save the file.
1223 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1224 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1225 UnloadPage(page);
1226
1227 // Re-open the file and check the prime marks are not there anymore.
Lei Zhang0b494052019-01-31 21:41:15 +00001228 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001229 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001230 ASSERT_TRUE(saved_page);
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001231
1232 CheckMarkCounts(saved_page, 1, kExpectedObjectCount, 0, 4, 9, 1);
1233
1234 CloseSavedPage(saved_page);
1235 CloseSavedDocument();
1236}
1237
Lei Zhangab41f252018-12-23 03:10:50 +00001238TEST_F(FPDFEditEmbedderTest, RemoveMarkParam) {
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001239 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001240 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001241 FPDF_PAGE page = LoadPage(0);
1242 ASSERT_TRUE(page);
1243
1244 constexpr int kExpectedObjectCount = 19;
1245 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
1246
1247 // Remove all "Square" content marks parameters.
1248 for (int i = 0; i < kExpectedObjectCount; ++i) {
1249 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1250
1251 int mark_count = FPDFPageObj_CountMarks(page_object);
1252 for (int j = 0; j < mark_count; ++j) {
1253 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
1254
1255 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001256 unsigned long name_len = 999u;
1257 ASSERT_TRUE(
1258 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
1259 EXPECT_GT(name_len, 0u);
1260 EXPECT_NE(999u, name_len);
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001261 std::wstring name =
1262 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1263 if (name == L"Square") {
1264 // Show the mark has a "Factor" parameter.
1265 int out_value;
1266 EXPECT_TRUE(
1267 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
1268
1269 // Remove parameter.
1270 EXPECT_TRUE(FPDFPageObjMark_RemoveParam(page_object, mark, "Factor"));
1271
1272 // Verify the "Factor" parameter is gone.
1273 EXPECT_FALSE(
1274 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
1275 }
1276 }
1277 }
1278
1279 // Save the file.
1280 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1281 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1282 UnloadPage(page);
1283
1284 // Re-open the file and check the "Factor" parameters are still gone.
Lei Zhang0b494052019-01-31 21:41:15 +00001285 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001286 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001287 ASSERT_TRUE(saved_page);
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001288
1289 size_t square_count = 0;
1290 for (int i = 0; i < kExpectedObjectCount; ++i) {
1291 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(saved_page, i);
1292
1293 int mark_count = FPDFPageObj_CountMarks(page_object);
1294 for (int j = 0; j < mark_count; ++j) {
1295 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
1296
1297 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001298 unsigned long name_len = 999u;
1299 ASSERT_TRUE(
1300 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
1301 EXPECT_GT(name_len, 0u);
1302 EXPECT_NE(999u, name_len);
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001303 std::wstring name =
1304 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1305 if (name == L"Square") {
1306 // Verify the "Factor" parameter is still gone.
1307 int out_value;
1308 EXPECT_FALSE(
1309 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
1310
1311 ++square_count;
1312 }
1313 }
1314 }
1315
1316 // Verify the parameters are gone, but the marks are not.
1317 EXPECT_EQ(4u, square_count);
1318
1319 CloseSavedPage(saved_page);
1320 CloseSavedDocument();
1321}
1322
Lei Zhangab41f252018-12-23 03:10:50 +00001323TEST_F(FPDFEditEmbedderTest, MaintainMarkedObjects) {
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001324 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001325 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001326 FPDF_PAGE page = LoadPage(0);
1327 ASSERT_TRUE(page);
1328
1329 // Iterate over all objects, counting the number of times each content mark
1330 // name appears.
1331 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
1332
1333 // Remove first page object.
1334 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1335 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1336 FPDFPageObj_Destroy(page_object);
1337
1338 CheckMarkCounts(page, 2, 18, 8, 3, 9, 1);
1339
1340 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1341 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1342
1343 UnloadPage(page);
1344
Lei Zhang0b494052019-01-31 21:41:15 +00001345 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001346 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001347 ASSERT_TRUE(saved_page);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001348
1349 CheckMarkCounts(saved_page, 2, 18, 8, 3, 9, 1);
1350
1351 CloseSavedPage(saved_page);
1352 CloseSavedDocument();
1353}
1354
Lei Zhangab41f252018-12-23 03:10:50 +00001355TEST_F(FPDFEditEmbedderTest, MaintainIndirectMarkedObjects) {
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001356 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001357 ASSERT_TRUE(OpenDocument("text_in_page_marked_indirect.pdf"));
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001358 FPDF_PAGE page = LoadPage(0);
1359 ASSERT_TRUE(page);
1360
1361 // Iterate over all objects, counting the number of times each content mark
1362 // name appears.
1363 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
1364
1365 // Remove first page object.
1366 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1367 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1368 FPDFPageObj_Destroy(page_object);
1369
1370 CheckMarkCounts(page, 2, 18, 8, 3, 9, 1);
1371
1372 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1373 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1374
1375 UnloadPage(page);
1376
Lei Zhang0b494052019-01-31 21:41:15 +00001377 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001378 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001379 ASSERT_TRUE(saved_page);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001380
1381 CheckMarkCounts(saved_page, 2, 18, 8, 3, 9, 1);
1382
1383 CloseSavedPage(saved_page);
1384 CloseSavedDocument();
1385}
1386
Lei Zhangab41f252018-12-23 03:10:50 +00001387TEST_F(FPDFEditEmbedderTest, RemoveExistingPageObject) {
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001388 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001389 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001390 FPDF_PAGE page = LoadPage(0);
1391 ASSERT_TRUE(page);
1392
1393 // Get the "Hello, world!" text object and remove it.
1394 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1395 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1396 ASSERT_TRUE(page_object);
1397 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1398
1399 // Verify the "Hello, world!" text is gone.
1400 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1401
1402 // Save the file
1403 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1404 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1405 UnloadPage(page);
1406 FPDFPageObj_Destroy(page_object);
1407
1408 // Re-open the file and check the page object count is still 1.
Lei Zhang0b494052019-01-31 21:41:15 +00001409 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001410 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001411 ASSERT_TRUE(saved_page);
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001412 EXPECT_EQ(1, FPDFPage_CountObjects(saved_page));
1413 CloseSavedPage(saved_page);
1414 CloseSavedDocument();
1415}
1416
Hui Yingstcb4203d2020-06-09 01:48:47 +00001417TEST_F(FPDFEditEmbedderTest, RemoveExistingPageObjectSplitStreamsNotLonely) {
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001418 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001419 ASSERT_TRUE(OpenDocument("hello_world_split_streams.pdf"));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001420 FPDF_PAGE page = LoadPage(0);
1421 ASSERT_TRUE(page);
1422
1423 // Get the "Hello, world!" text object and remove it. There is another object
1424 // in the same stream that says "Goodbye, world!"
1425 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1426 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1427 ASSERT_TRUE(page_object);
1428 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1429
1430 // Verify the "Hello, world!" text is gone.
1431 ASSERT_EQ(2, FPDFPage_CountObjects(page));
Hui Yingstcb4203d2020-06-09 01:48:47 +00001432#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingstcb4203d2020-06-09 01:48:47 +00001433 const char kHelloRemovedChecksum[] = "deed7dc2754dc80930f3b05e2ac86c94";
Hui Yingstcb4203d2020-06-09 01:48:47 +00001434#else
1435#if defined(OS_WIN)
Hui Yingst282f0b82021-08-30 22:59:52 +00001436 const char kHelloRemovedChecksum[] = "55c45c5f13230f504c2e3b9e8d0347a0";
Lei Zhang0c03d632020-07-30 17:05:36 +00001437#elif defined(OS_APPLE)
Hui Yingstcb4203d2020-06-09 01:48:47 +00001438 const char kHelloRemovedChecksum[] = "3b3b27602a86dfe5996a33c42c59885b";
1439#else
1440 const char kHelloRemovedChecksum[] = "95b92950647a2190e1230911e7a1a0e9";
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001441#endif
Hui Yingstcb4203d2020-06-09 01:48:47 +00001442#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001443 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001444 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstcb4203d2020-06-09 01:48:47 +00001445 CompareBitmap(page_bitmap.get(), 200, 200, kHelloRemovedChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001446 }
1447
1448 // Save the file
1449 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1450 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1451 UnloadPage(page);
1452 FPDFPageObj_Destroy(page_object);
1453
1454 // Re-open the file and check the page object count is still 2.
Lei Zhang0b494052019-01-31 21:41:15 +00001455 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001456 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001457 ASSERT_TRUE(saved_page);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001458
1459 EXPECT_EQ(2, FPDFPage_CountObjects(saved_page));
1460 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001461 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstcb4203d2020-06-09 01:48:47 +00001462 CompareBitmap(page_bitmap.get(), 200, 200, kHelloRemovedChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001463 }
1464
1465 CloseSavedPage(saved_page);
1466 CloseSavedDocument();
1467}
1468
Hui Yingst08c40712020-04-29 01:37:35 +00001469TEST_F(FPDFEditEmbedderTest, RemoveExistingPageObjectSplitStreamsLonely) {
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001470 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001471 ASSERT_TRUE(OpenDocument("hello_world_split_streams.pdf"));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001472 FPDF_PAGE page = LoadPage(0);
1473 ASSERT_TRUE(page);
1474
1475 // Get the "Greetings, world!" text object and remove it. This is the only
1476 // object in the stream.
1477 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1478 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 2);
1479 ASSERT_TRUE(page_object);
1480 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1481
1482 // Verify the "Greetings, world!" text is gone.
1483 ASSERT_EQ(2, FPDFPage_CountObjects(page));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001484 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001485 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001486 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001487 }
1488
1489 // Save the file
1490 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1491 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1492 UnloadPage(page);
1493 FPDFPageObj_Destroy(page_object);
1494
1495 // Re-open the file and check the page object count is still 2.
Lei Zhang0b494052019-01-31 21:41:15 +00001496 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001497 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001498 ASSERT_TRUE(saved_page);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001499
1500 EXPECT_EQ(2, FPDFPage_CountObjects(saved_page));
1501 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001502 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001503 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001504 }
1505
1506 CloseSavedPage(saved_page);
1507 CloseSavedDocument();
1508}
1509
Lei Zhangab41f252018-12-23 03:10:50 +00001510TEST_F(FPDFEditEmbedderTest, GetContentStream) {
Henrique Nakashima6eb79392018-06-12 20:27:35 +00001511 // Load document with some text split across streams.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001512 ASSERT_TRUE(OpenDocument("split_streams.pdf"));
Henrique Nakashima6eb79392018-06-12 20:27:35 +00001513 FPDF_PAGE page = LoadPage(0);
1514 ASSERT_TRUE(page);
1515
1516 // Content stream 0: page objects 0-14.
1517 // Content stream 1: page objects 15-17.
1518 // Content stream 2: page object 18.
1519 ASSERT_EQ(19, FPDFPage_CountObjects(page));
1520 for (int i = 0; i < 19; i++) {
1521 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1522 ASSERT_TRUE(page_object);
1523 CPDF_PageObject* cpdf_page_object =
1524 CPDFPageObjectFromFPDFPageObject(page_object);
1525 if (i < 15)
1526 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1527 else if (i < 18)
1528 EXPECT_EQ(1, cpdf_page_object->GetContentStream()) << i;
1529 else
1530 EXPECT_EQ(2, cpdf_page_object->GetContentStream()) << i;
1531 }
1532
1533 UnloadPage(page);
1534}
1535
Hui Yingst0d692fe2020-11-06 17:32:50 +00001536TEST_F(FPDFEditEmbedderTest, RemoveAllFromStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001537 // Load document with some text split across streams.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001538 ASSERT_TRUE(OpenDocument("split_streams.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001539 FPDF_PAGE page = LoadPage(0);
1540 ASSERT_TRUE(page);
1541
1542 // Content stream 0: page objects 0-14.
1543 // Content stream 1: page objects 15-17.
1544 // Content stream 2: page object 18.
1545 ASSERT_EQ(19, FPDFPage_CountObjects(page));
1546
1547 // Loop backwards because objects will being removed, which shifts the indexes
1548 // after the removed position.
1549 for (int i = 18; i >= 0; i--) {
1550 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1551 ASSERT_TRUE(page_object);
1552 CPDF_PageObject* cpdf_page_object =
1553 CPDFPageObjectFromFPDFPageObject(page_object);
1554
1555 // Empty content stream 1.
1556 if (cpdf_page_object->GetContentStream() == 1) {
1557 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1558 FPDFPageObj_Destroy(page_object);
1559 }
1560 }
1561
1562 // Content stream 0: page objects 0-14.
1563 // Content stream 2: page object 15.
1564 ASSERT_EQ(16, FPDFPage_CountObjects(page));
1565 for (int i = 0; i < 16; i++) {
1566 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1567 ASSERT_TRUE(page_object);
1568 CPDF_PageObject* cpdf_page_object =
1569 CPDFPageObjectFromFPDFPageObject(page_object);
1570 if (i < 15)
1571 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1572 else
1573 EXPECT_EQ(2, cpdf_page_object->GetContentStream()) << i;
1574 }
1575
1576 // Generate contents should remove the empty stream and update the page
1577 // objects' contents stream indexes.
1578 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1579
1580 // Content stream 0: page objects 0-14.
1581 // Content stream 1: page object 15.
1582 ASSERT_EQ(16, FPDFPage_CountObjects(page));
1583 for (int i = 0; i < 16; i++) {
1584 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1585 ASSERT_TRUE(page_object);
1586 CPDF_PageObject* cpdf_page_object =
1587 CPDFPageObjectFromFPDFPageObject(page_object);
1588 if (i < 15)
1589 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1590 else
1591 EXPECT_EQ(1, cpdf_page_object->GetContentStream()) << i;
1592 }
1593
Hui Yingst0d692fe2020-11-06 17:32:50 +00001594#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1595 const char kStream1RemovedChecksum[] = "89358c444a398b0b56b35738edd8fe43";
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001596#else
Hui Yingst282f0b82021-08-30 22:59:52 +00001597#if defined(OS_APPLE)
Hui Yingst0d692fe2020-11-06 17:32:50 +00001598 const char kStream1RemovedChecksum[] = "0e8856ca9abc7049412e64f9230c7c43";
1599#else
1600 const char kStream1RemovedChecksum[] = "e86a3efc160ede6cfcb1f59bcacf1105";
Hui Yingst282f0b82021-08-30 22:59:52 +00001601#endif // defined(OS_APPLE)
Hui Yingst0d692fe2020-11-06 17:32:50 +00001602#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001603 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001604 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst0d692fe2020-11-06 17:32:50 +00001605 CompareBitmap(page_bitmap.get(), 200, 200, kStream1RemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001606 }
1607
1608 // Save the file
1609 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1610 UnloadPage(page);
1611
1612 // Re-open the file and check the page object count is still 16, and that
1613 // content stream 1 was removed.
Lei Zhang0b494052019-01-31 21:41:15 +00001614 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001615 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001616 ASSERT_TRUE(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001617
1618 // Content stream 0: page objects 0-14.
1619 // Content stream 1: page object 15.
1620 EXPECT_EQ(16, FPDFPage_CountObjects(saved_page));
1621 for (int i = 0; i < 16; i++) {
1622 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(saved_page, i);
1623 ASSERT_TRUE(page_object);
1624 CPDF_PageObject* cpdf_page_object =
1625 CPDFPageObjectFromFPDFPageObject(page_object);
1626 if (i < 15)
1627 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1628 else
1629 EXPECT_EQ(1, cpdf_page_object->GetContentStream()) << i;
1630 }
1631
1632 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001633 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingst0d692fe2020-11-06 17:32:50 +00001634 CompareBitmap(page_bitmap.get(), 200, 200, kStream1RemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001635 }
1636
1637 CloseSavedPage(saved_page);
1638 CloseSavedDocument();
1639}
1640
Lei Zhangab41f252018-12-23 03:10:50 +00001641TEST_F(FPDFEditEmbedderTest, RemoveAllFromSingleStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001642 // Load document with a single stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001643 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001644 FPDF_PAGE page = LoadPage(0);
1645 ASSERT_TRUE(page);
1646
1647 // Content stream 0: page objects 0-1.
1648 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1649
1650 // Loop backwards because objects will being removed, which shifts the indexes
1651 // after the removed position.
1652 for (int i = 1; i >= 0; i--) {
1653 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1654 ASSERT_TRUE(page_object);
1655 CPDF_PageObject* cpdf_page_object =
1656 CPDFPageObjectFromFPDFPageObject(page_object);
1657 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1658 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1659 FPDFPageObj_Destroy(page_object);
1660 }
1661
1662 // No more objects in the stream
1663 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1664
1665 // Generate contents should remove the empty stream and update the page
1666 // objects' contents stream indexes.
1667 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1668
1669 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1670
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001671 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001672 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001673 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001674 }
1675
1676 // Save the file
1677 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1678 UnloadPage(page);
1679
1680 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001681 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001682 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001683 ASSERT_TRUE(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001684
1685 EXPECT_EQ(0, FPDFPage_CountObjects(saved_page));
1686 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001687 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001688 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001689 }
1690
1691 CloseSavedPage(saved_page);
1692 CloseSavedDocument();
1693}
1694
Hui Yingst08c40712020-04-29 01:37:35 +00001695TEST_F(FPDFEditEmbedderTest, RemoveFirstFromSingleStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001696 // Load document with a single stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001697 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001698 FPDF_PAGE page = LoadPage(0);
1699 ASSERT_TRUE(page);
1700
1701 // Content stream 0: page objects 0-1.
1702 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1703
1704 // Remove first object.
1705 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1706 ASSERT_TRUE(page_object);
1707 CPDF_PageObject* cpdf_page_object =
1708 CPDFPageObjectFromFPDFPageObject(page_object);
1709 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1710 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1711 FPDFPageObj_Destroy(page_object);
1712
1713 // One object left in the stream.
1714 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1715 page_object = FPDFPage_GetObject(page, 0);
1716 ASSERT_TRUE(page_object);
1717 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1718 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1719
1720 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1721
1722 // Still one object left in the stream.
1723 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1724 page_object = FPDFPage_GetObject(page, 0);
1725 ASSERT_TRUE(page_object);
1726 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1727 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1728
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001729 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001730 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001731 CompareBitmap(page_bitmap.get(), 200, 200, kFirstRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001732 }
1733
1734 // Save the file
1735 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1736 UnloadPage(page);
1737
1738 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001739 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001740 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001741 ASSERT_TRUE(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001742
1743 ASSERT_EQ(1, FPDFPage_CountObjects(saved_page));
1744 page_object = FPDFPage_GetObject(saved_page, 0);
1745 ASSERT_TRUE(page_object);
1746 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1747 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1748 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001749 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001750 CompareBitmap(page_bitmap.get(), 200, 200, kFirstRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001751 }
1752
1753 CloseSavedPage(saved_page);
1754 CloseSavedDocument();
1755}
1756
Hui Yingst08c40712020-04-29 01:37:35 +00001757TEST_F(FPDFEditEmbedderTest, RemoveLastFromSingleStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001758 // Load document with a single stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001759 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001760 FPDF_PAGE page = LoadPage(0);
1761 ASSERT_TRUE(page);
1762
1763 // Content stream 0: page objects 0-1.
1764 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1765
1766 // Remove last object
1767 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 1);
1768 ASSERT_TRUE(page_object);
1769 CPDF_PageObject* cpdf_page_object =
1770 CPDFPageObjectFromFPDFPageObject(page_object);
1771 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1772 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1773 FPDFPageObj_Destroy(page_object);
1774
1775 // One object left in the stream.
1776 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1777 page_object = FPDFPage_GetObject(page, 0);
1778 ASSERT_TRUE(page_object);
1779 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1780 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1781
1782 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1783
1784 // Still one object left in the stream.
1785 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1786 page_object = FPDFPage_GetObject(page, 0);
1787 ASSERT_TRUE(page_object);
1788 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1789 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1790
Hui Yingstb4baceb2020-04-28 23:46:10 +00001791 using pdfium::kHelloWorldRemovedChecksum;
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001792 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001793 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001794 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001795 }
1796
1797 // Save the file
1798 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1799 UnloadPage(page);
1800
1801 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001802 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001803 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001804 ASSERT_TRUE(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001805
1806 ASSERT_EQ(1, FPDFPage_CountObjects(saved_page));
1807 page_object = FPDFPage_GetObject(saved_page, 0);
1808 ASSERT_TRUE(page_object);
1809 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1810 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1811 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001812 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001813 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001814 }
1815
1816 CloseSavedPage(saved_page);
1817 CloseSavedDocument();
1818}
1819
Lei Zhangab41f252018-12-23 03:10:50 +00001820TEST_F(FPDFEditEmbedderTest, RemoveAllFromMultipleStreams) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001821 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001822 ASSERT_TRUE(OpenDocument("hello_world_split_streams.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001823 FPDF_PAGE page = LoadPage(0);
1824 ASSERT_TRUE(page);
1825
1826 // Content stream 0: page objects 0-1.
1827 // Content stream 1: page object 2.
1828 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1829
1830 // Loop backwards because objects will being removed, which shifts the indexes
1831 // after the removed position.
1832 for (int i = 2; i >= 0; i--) {
1833 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1834 ASSERT_TRUE(page_object);
1835 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1836 FPDFPageObj_Destroy(page_object);
1837 }
1838
1839 // No more objects in the page.
1840 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1841
1842 // Generate contents should remove the empty streams and update the page
1843 // objects' contents stream indexes.
1844 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1845
1846 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1847
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001848 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001849 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001850 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001851 }
1852
1853 // Save the file
1854 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1855 UnloadPage(page);
1856
1857 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001858 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001859 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001860 ASSERT_TRUE(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001861
1862 EXPECT_EQ(0, FPDFPage_CountObjects(saved_page));
1863 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001864 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001865 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001866 }
1867
1868 CloseSavedPage(saved_page);
1869 CloseSavedDocument();
1870}
1871
Lei Zhangab41f252018-12-23 03:10:50 +00001872TEST_F(FPDFEditEmbedderTest, InsertPageObjectAndSave) {
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001873 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001874 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001875 FPDF_PAGE page = LoadPage(0);
1876 ASSERT_TRUE(page);
1877
1878 // Add a red rectangle.
1879 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1880 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001881 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001882 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
1883 FPDFPage_InsertObject(page, red_rect);
1884
1885 // Verify the red rectangle was added.
1886 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1887
1888 // Save the file
1889 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1890 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1891 UnloadPage(page);
1892
1893 // Re-open the file and check the page object count is still 3.
Lei Zhang0b494052019-01-31 21:41:15 +00001894 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001895 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001896 ASSERT_TRUE(saved_page);
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001897 EXPECT_EQ(3, FPDFPage_CountObjects(saved_page));
1898 CloseSavedPage(saved_page);
1899 CloseSavedDocument();
1900}
1901
Lei Zhangab41f252018-12-23 03:10:50 +00001902TEST_F(FPDFEditEmbedderTest, InsertPageObjectEditAndSave) {
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001903 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001904 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001905 FPDF_PAGE page = LoadPage(0);
1906 ASSERT_TRUE(page);
1907
1908 // Add a red rectangle.
1909 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1910 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001911 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 100, 100, 255));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001912 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
1913 FPDFPage_InsertObject(page, red_rect);
1914
1915 // Verify the red rectangle was added.
1916 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1917
1918 // Generate content but change it again
1919 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhang3475b482019-05-13 18:30:57 +00001920 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001921
1922 // Save the file
1923 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1924 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1925 UnloadPage(page);
1926
1927 // Re-open the file and check the page object count is still 3.
Lei Zhang0b494052019-01-31 21:41:15 +00001928 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001929 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001930 ASSERT_TRUE(saved_page);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001931 EXPECT_EQ(3, FPDFPage_CountObjects(saved_page));
1932 CloseSavedPage(saved_page);
1933 CloseSavedDocument();
1934}
1935
Hui Yingst8b5dfb22020-07-21 17:08:30 +00001936TEST_F(FPDFEditEmbedderTest, InsertAndRemoveLargeFile) {
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001937 const int kOriginalObjectCount = 600;
1938
1939 // Load document with many objects.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001940 ASSERT_TRUE(OpenDocument("many_rectangles.pdf"));
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001941 FPDF_PAGE page = LoadPage(0);
1942 ASSERT_TRUE(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001943
1944 using pdfium::kManyRectanglesChecksum;
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001945 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001946 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001947 CompareBitmap(page_bitmap.get(), 200, 300, kManyRectanglesChecksum);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001948 }
1949
1950 // Add a black rectangle.
1951 ASSERT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(page));
1952 FPDF_PAGEOBJECT black_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001953 EXPECT_TRUE(FPDFPageObj_SetFillColor(black_rect, 0, 0, 0, 255));
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001954 EXPECT_TRUE(FPDFPath_SetDrawMode(black_rect, FPDF_FILLMODE_ALTERNATE, 0));
1955 FPDFPage_InsertObject(page, black_rect);
1956
1957 // Verify the black rectangle was added.
1958 ASSERT_EQ(kOriginalObjectCount + 1, FPDFPage_CountObjects(page));
Hui Yingst8b5dfb22020-07-21 17:08:30 +00001959#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1960 const char kPlusRectangleMD5[] = "0d3715fcfb9bd0dd25dcce60800bff47";
1961#else
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001962 const char kPlusRectangleMD5[] = "6b9396ab570754b32b04ca629e902f77";
Hui Yingst8b5dfb22020-07-21 17:08:30 +00001963#endif
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001964 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001965 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001966 CompareBitmap(page_bitmap.get(), 200, 300, kPlusRectangleMD5);
1967 }
1968
1969 // Save the file.
1970 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1971 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1972 UnloadPage(page);
1973
1974 // Re-open the file and check the rectangle added is still there.
Lei Zhang0b494052019-01-31 21:41:15 +00001975 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001976 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001977 ASSERT_TRUE(saved_page);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001978 EXPECT_EQ(kOriginalObjectCount + 1, FPDFPage_CountObjects(saved_page));
1979 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001980 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001981 CompareBitmap(page_bitmap.get(), 200, 300, kPlusRectangleMD5);
1982 }
1983
1984 // Remove the added rectangle.
1985 FPDF_PAGEOBJECT added_object =
1986 FPDFPage_GetObject(saved_page, kOriginalObjectCount);
1987 EXPECT_TRUE(FPDFPage_RemoveObject(saved_page, added_object));
1988 FPDFPageObj_Destroy(added_object);
1989 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001990 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001991 CompareBitmap(page_bitmap.get(), 200, 300, kManyRectanglesChecksum);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001992 }
1993 EXPECT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(saved_page));
1994
1995 // Save the file again.
1996 EXPECT_TRUE(FPDFPage_GenerateContent(saved_page));
Lei Zhang38e2b0e2021-11-05 00:28:05 +00001997 EXPECT_TRUE(FPDF_SaveAsCopy(saved_document(), this, 0));
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001998
1999 CloseSavedPage(saved_page);
2000 CloseSavedDocument();
2001
2002 // Re-open the file (again) and check the black rectangle was removed and the
2003 // rest is intact.
Lei Zhang0b494052019-01-31 21:41:15 +00002004 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00002005 saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00002006 ASSERT_TRUE(saved_page);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00002007 EXPECT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(saved_page));
2008 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002009 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00002010 CompareBitmap(page_bitmap.get(), 200, 300, kManyRectanglesChecksum);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00002011 }
2012
2013 CloseSavedPage(saved_page);
2014 CloseSavedDocument();
2015}
2016
Lei Zhangab41f252018-12-23 03:10:50 +00002017TEST_F(FPDFEditEmbedderTest, AddAndRemovePaths) {
Henrique Nakashima35841fa2018-03-15 15:25:16 +00002018 // Start with a blank page.
2019 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
2020 ASSERT_TRUE(page);
2021
2022 // Render the blank page and verify it's a blank bitmap.
Hui Yingstb4baceb2020-04-28 23:46:10 +00002023 using pdfium::kBlankPage612By792Checksum;
Henrique Nakashima35841fa2018-03-15 15:25:16 +00002024 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002025 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00002026 CompareBitmap(page_bitmap.get(), 612, 792, kBlankPage612By792Checksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00002027 }
2028 ASSERT_EQ(0, FPDFPage_CountObjects(page));
2029
2030 // Add a red rectangle.
2031 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
2032 ASSERT_TRUE(red_rect);
Lei Zhang3475b482019-05-13 18:30:57 +00002033 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Henrique Nakashima35841fa2018-03-15 15:25:16 +00002034 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
2035 FPDFPage_InsertObject(page, red_rect);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00002036 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002037 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00002038 CompareBitmap(page_bitmap.get(), 612, 792, kRedRectangleChecksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00002039 }
2040 EXPECT_EQ(1, FPDFPage_CountObjects(page));
2041
2042 // Remove rectangle and verify it does not render anymore and the bitmap is
2043 // back to a blank one.
2044 EXPECT_TRUE(FPDFPage_RemoveObject(page, red_rect));
2045 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002046 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00002047 CompareBitmap(page_bitmap.get(), 612, 792, kBlankPage612By792Checksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00002048 }
2049 EXPECT_EQ(0, FPDFPage_CountObjects(page));
2050
2051 // Trying to remove an object not in the page should return false.
2052 EXPECT_FALSE(FPDFPage_RemoveObject(page, red_rect));
2053
2054 FPDF_ClosePage(page);
2055 FPDFPageObj_Destroy(red_rect);
2056}
2057
Lei Zhangab41f252018-12-23 03:10:50 +00002058TEST_F(FPDFEditEmbedderTest, PathsPoints) {
Miklos Vajna12abfd02017-09-15 07:49:03 +02002059 CreateNewDocument();
Lei Zhang38e2b0e2021-11-05 00:28:05 +00002060 FPDF_PAGEOBJECT img = FPDFPageObj_NewImageObj(document());
Miklos Vajna12abfd02017-09-15 07:49:03 +02002061 // This should fail gracefully, even if img is not a path.
Miklos Vajna0150a542017-09-21 21:46:56 +02002062 ASSERT_EQ(-1, FPDFPath_CountSegments(img));
Miklos Vajna12abfd02017-09-15 07:49:03 +02002063
2064 // This should fail gracefully, even if path is NULL.
Miklos Vajna0150a542017-09-21 21:46:56 +02002065 ASSERT_EQ(-1, FPDFPath_CountSegments(nullptr));
Miklos Vajna12abfd02017-09-15 07:49:03 +02002066
Miklos Vajna36eed872017-09-20 22:52:43 +02002067 // FPDFPath_GetPathSegment() with a non-path.
2068 ASSERT_EQ(nullptr, FPDFPath_GetPathSegment(img, 0));
2069 // FPDFPath_GetPathSegment() with a NULL path.
2070 ASSERT_EQ(nullptr, FPDFPath_GetPathSegment(nullptr, 0));
2071 float x;
2072 float y;
2073 // FPDFPathSegment_GetPoint() with a NULL segment.
2074 EXPECT_FALSE(FPDFPathSegment_GetPoint(nullptr, &x, &y));
2075
2076 // FPDFPathSegment_GetType() with a NULL segment.
2077 ASSERT_EQ(FPDF_SEGMENT_UNKNOWN, FPDFPathSegment_GetType(nullptr));
2078
2079 // FPDFPathSegment_GetClose() with a NULL segment.
2080 EXPECT_FALSE(FPDFPathSegment_GetClose(nullptr));
2081
Miklos Vajna12abfd02017-09-15 07:49:03 +02002082 FPDFPageObj_Destroy(img);
2083}
2084
Hui Yingste95d5772020-08-24 23:58:26 +00002085TEST_F(FPDFEditEmbedderTest, PathOnTopOfText) {
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002086 // Load document with some text
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002087 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002088 FPDF_PAGE page = LoadPage(0);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002089 ASSERT_TRUE(page);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002090
2091 // Add an opaque rectangle on top of some of the text.
2092 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002093 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002094 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
2095 FPDFPage_InsertObject(page, red_rect);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002096
2097 // Add a transparent triangle on top of other part of the text.
2098 FPDF_PAGEOBJECT black_path = FPDFPageObj_CreateNewPath(20, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002099 EXPECT_TRUE(FPDFPageObj_SetFillColor(black_path, 0, 0, 0, 100));
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002100 EXPECT_TRUE(FPDFPath_SetDrawMode(black_path, FPDF_FILLMODE_ALTERNATE, 0));
2101 EXPECT_TRUE(FPDFPath_LineTo(black_path, 30, 80));
2102 EXPECT_TRUE(FPDFPath_LineTo(black_path, 40, 10));
2103 EXPECT_TRUE(FPDFPath_Close(black_path));
2104 FPDFPage_InsertObject(page, black_path);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002105
Hui Yingste95d5772020-08-24 23:58:26 +00002106 // Render and check the result.
Tom Sepeze08d2b12018-04-25 18:49:32 +00002107 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
Hui Yingste95d5772020-08-24 23:58:26 +00002108#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingste95d5772020-08-24 23:58:26 +00002109 const char kChecksum[] = "d082f9756c86bb47e1abbc2b1df7138a";
Hui Yingste95d5772020-08-24 23:58:26 +00002110#else
2111#if defined(OS_WIN)
2112 const char kChecksum[] = "74dd9c393b8b2578d2b7feb032b7daad";
2113#elif defined(OS_APPLE)
2114 const char kChecksum[] = "e55bcd1facb7243dc6e16dd5f912265b";
2115#else
2116 const char kChecksum[] = "aa71b09b93b55f467f1290e5111babee";
Nicolas Pena5bcd9a32017-03-22 11:04:35 -04002117#endif
Hui Yingste95d5772020-08-24 23:58:26 +00002118#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2119 CompareBitmap(bitmap.get(), 200, 200, kChecksum);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002120 UnloadPage(page);
2121}
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002122
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002123TEST_F(FPDFEditEmbedderTest, EditOverExistingContent) {
wileyryae858aa42017-05-31 14:49:05 -05002124 // Load document with existing content
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002125 ASSERT_TRUE(OpenDocument("bug_717.pdf"));
wileyryae858aa42017-05-31 14:49:05 -05002126 FPDF_PAGE page = LoadPage(0);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002127 ASSERT_TRUE(page);
wileyryae858aa42017-05-31 14:49:05 -05002128
2129 // Add a transparent rectangle on top of the existing content
2130 FPDF_PAGEOBJECT red_rect2 = FPDFPageObj_CreateNewRect(90, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002131 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect2, 255, 0, 0, 100));
wileyryae858aa42017-05-31 14:49:05 -05002132 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect2, FPDF_FILLMODE_ALTERNATE, 0));
2133 FPDFPage_InsertObject(page, red_rect2);
2134
2135 // Add an opaque rectangle on top of the existing content
2136 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(115, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002137 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
wileyryae858aa42017-05-31 14:49:05 -05002138 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
2139 FPDFPage_InsertObject(page, red_rect);
2140
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002141#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2142 const char kOriginalChecksum[] = "1e82fbdd21490cee9d3479fe6125af67";
2143#else
2144 const char kOriginalChecksum[] = "ad04e5bd0f471a9a564fb034bd0fb073";
2145#endif
Tom Sepeze08d2b12018-04-25 18:49:32 +00002146 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002147 CompareBitmap(bitmap.get(), 612, 792, kOriginalChecksum);
wileyryae858aa42017-05-31 14:49:05 -05002148 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2149
2150 // Now save the result, closing the page and document
2151 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Nicolas Pena3ff54002017-07-05 11:55:35 -04002152 UnloadPage(page);
wileyryae858aa42017-05-31 14:49:05 -05002153
Lei Zhang0b494052019-01-31 21:41:15 +00002154 ASSERT_TRUE(OpenSavedDocument());
Lei Zhang107fa7b2018-02-09 21:48:15 +00002155 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00002156 ASSERT_TRUE(saved_page);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002157 VerifySavedRendering(saved_page, 612, 792, kOriginalChecksum);
wileyryae858aa42017-05-31 14:49:05 -05002158
2159 ClearString();
2160 // Add another opaque rectangle on top of the existing content
2161 FPDF_PAGEOBJECT green_rect = FPDFPageObj_CreateNewRect(150, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002162 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_rect, 0, 255, 0, 255));
wileyryae858aa42017-05-31 14:49:05 -05002163 EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect, FPDF_FILLMODE_ALTERNATE, 0));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002164 FPDFPage_InsertObject(saved_page, green_rect);
wileyryae858aa42017-05-31 14:49:05 -05002165
2166 // Add another transparent rectangle on top of existing content
2167 FPDF_PAGEOBJECT green_rect2 = FPDFPageObj_CreateNewRect(175, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002168 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_rect2, 0, 255, 0, 100));
wileyryae858aa42017-05-31 14:49:05 -05002169 EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect2, FPDF_FILLMODE_ALTERNATE, 0));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002170 FPDFPage_InsertObject(saved_page, green_rect2);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002171#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2172 const char kLastChecksum[] = "8705d023e5fec3499d1e30cf2bcc5dc1";
2173#else
2174 const char kLastChecksum[] = "4b5b00f824620f8c9b8801ebb98e1cdd";
2175#endif
Lei Zhangc113c7a2018-02-12 14:58:44 +00002176 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00002177 ScopedFPDFBitmap new_bitmap = RenderSavedPage(saved_page);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002178 CompareBitmap(new_bitmap.get(), 612, 792, kLastChecksum);
Lei Zhangc113c7a2018-02-12 14:58:44 +00002179 }
Lei Zhang107fa7b2018-02-09 21:48:15 +00002180 EXPECT_TRUE(FPDFPage_GenerateContent(saved_page));
wileyryae858aa42017-05-31 14:49:05 -05002181
2182 // Now save the result, closing the page and document
Lei Zhang38e2b0e2021-11-05 00:28:05 +00002183 EXPECT_TRUE(FPDF_SaveAsCopy(saved_document(), this, 0));
Dan Sinclair04e4dc82017-10-18 12:17:14 -04002184
Lei Zhang107fa7b2018-02-09 21:48:15 +00002185 CloseSavedPage(saved_page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04002186 CloseSavedDocument();
wileyryae858aa42017-05-31 14:49:05 -05002187
2188 // Render the saved result
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002189 VerifySavedDocument(612, 792, kLastChecksum);
wileyryae858aa42017-05-31 14:49:05 -05002190}
2191
Hui Yingst041116e2021-03-01 21:27:50 +00002192// TODO(crbug.com/pdfium/1651): Fix this issue and enable the test for Skia.
2193#if defined(_SKIA_SUPPORT_)
Lei Zhang03e5e682019-09-16 19:45:55 +00002194#define MAYBE_AddStrokedPaths DISABLED_AddStrokedPaths
2195#else
2196#define MAYBE_AddStrokedPaths AddStrokedPaths
2197#endif
2198TEST_F(FPDFEditEmbedderTest, MAYBE_AddStrokedPaths) {
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002199 // Start with a blank page
Nicolas Penad03ca422017-03-06 13:54:33 -05002200 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002201
2202 // Add a large stroked rectangle (fill color should not affect it).
2203 FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(20, 20, 200, 400);
Lei Zhang3475b482019-05-13 18:30:57 +00002204 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect, 255, 0, 0, 255));
2205 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(rect, 0, 255, 0, 255));
2206 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(rect, 15.0f));
Miklos Vajna366df7f2018-05-22 14:27:29 +00002207
2208 float width = 0;
2209 EXPECT_TRUE(FPDFPageObj_GetStrokeWidth(rect, &width));
2210 EXPECT_EQ(15.0f, width);
2211
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002212 EXPECT_TRUE(FPDFPath_SetDrawMode(rect, 0, 1));
2213 FPDFPage_InsertObject(page, rect);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002214 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002215 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst041116e2021-03-01 21:27:50 +00002216#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2217 static constexpr char kChecksum_1[] = "1469acf60e7647ebeb8e1fb08c5d6c7a";
2218#else
2219 static constexpr char kChecksum_1[] = "64bd31f862a89e0a9e505a5af6efd506";
2220#endif
2221 CompareBitmap(page_bitmap.get(), 612, 792, kChecksum_1);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002222 }
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002223
2224 // Add crossed-checkmark
2225 FPDF_PAGEOBJECT check = FPDFPageObj_CreateNewPath(300, 500);
2226 EXPECT_TRUE(FPDFPath_LineTo(check, 400, 400));
2227 EXPECT_TRUE(FPDFPath_LineTo(check, 600, 600));
2228 EXPECT_TRUE(FPDFPath_MoveTo(check, 400, 600));
2229 EXPECT_TRUE(FPDFPath_LineTo(check, 600, 400));
Lei Zhang3475b482019-05-13 18:30:57 +00002230 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(check, 128, 128, 128, 180));
2231 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(check, 8.35f));
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002232 EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1));
2233 FPDFPage_InsertObject(page, check);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002234 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002235 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst041116e2021-03-01 21:27:50 +00002236#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2237 static constexpr char kChecksum_2[] = "68b3194f74abd9d471695ce1415be43f";
2238#else
2239 static constexpr char kChecksum_2[] = "4b6f3b9d25c4e194821217d5016c3724";
2240#endif
2241 CompareBitmap(page_bitmap.get(), 612, 792, kChecksum_2);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002242 }
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002243
2244 // Add stroked and filled oval-ish path.
2245 FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(250, 100);
2246 EXPECT_TRUE(FPDFPath_BezierTo(path, 180, 166, 180, 233, 250, 300));
2247 EXPECT_TRUE(FPDFPath_LineTo(path, 255, 305));
2248 EXPECT_TRUE(FPDFPath_BezierTo(path, 325, 233, 325, 166, 255, 105));
2249 EXPECT_TRUE(FPDFPath_Close(path));
Lei Zhang3475b482019-05-13 18:30:57 +00002250 EXPECT_TRUE(FPDFPageObj_SetFillColor(path, 200, 128, 128, 100));
2251 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(path, 128, 200, 128, 150));
2252 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(path, 10.5f));
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002253 EXPECT_TRUE(FPDFPath_SetDrawMode(path, FPDF_FILLMODE_ALTERNATE, 1));
2254 FPDFPage_InsertObject(page, path);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002255 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002256 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst041116e2021-03-01 21:27:50 +00002257#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2258 static constexpr char kChecksum_3[] = "ea784068651df2b9ba132ce9215e6780";
2259#else
2260 static constexpr char kChecksum_3[] = "ff3e6a22326754944cc6e56609acd73b";
2261#endif
2262 CompareBitmap(page_bitmap.get(), 612, 792, kChecksum_3);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002263 }
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002264 FPDF_ClosePage(page);
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002265}
Nicolas Pena49058402017-02-14 18:26:20 -05002266
Nicolas Pena4c48b102018-06-13 18:23:46 +00002267// Tests adding text from standard font using FPDFPageObj_NewTextObj.
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002268TEST_F(FPDFEditEmbedderTest, AddStandardFontText) {
Nicolas Pena49058402017-02-14 18:26:20 -05002269 // Start with a blank page
Lei Zhang8496d132021-07-08 04:34:34 +00002270 ScopedFPDFPage page(FPDFPage_New(CreateNewDocument(), 0, 612, 792));
Nicolas Pena49058402017-02-14 18:26:20 -05002271
2272 // Add some text to the page
Nicolas Penab3161852017-05-02 14:12:50 -04002273 FPDF_PAGEOBJECT text_object1 =
2274 FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
2275 EXPECT_TRUE(text_object1);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002276 ScopedFPDFWideString text1 = GetFPDFWideString(kBottomText);
Nicolas Penab3161852017-05-02 14:12:50 -04002277 EXPECT_TRUE(FPDFText_SetText(text_object1, text1.get()));
Lei Zhangcfd08172021-06-30 04:11:21 +00002278 static constexpr FS_MATRIX kMatrix1{1, 0, 0, 1, 20, 20};
2279 EXPECT_TRUE(FPDFPageObj_SetMatrix(text_object1, &kMatrix1));
Lei Zhang8496d132021-07-08 04:34:34 +00002280 FPDFPage_InsertObject(page.get(), text_object1);
2281 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002282 {
Lei Zhang8496d132021-07-08 04:34:34 +00002283 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
Hui Yingst3b6136a2020-06-09 00:39:33 +00002284 CompareBitmap(page_bitmap.get(), 612, 792, kBottomTextChecksum);
Lei Zhange039bab2019-03-18 19:57:56 +00002285
2286 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Hui Yingst3b6136a2020-06-09 00:39:33 +00002287 VerifySavedDocument(612, 792, kBottomTextChecksum);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002288 }
Nicolas Pena49058402017-02-14 18:26:20 -05002289
2290 // Try another font
Nicolas Penab3161852017-05-02 14:12:50 -04002291 FPDF_PAGEOBJECT text_object2 =
Nicolas Penad03ca422017-03-06 13:54:33 -05002292 FPDFPageObj_NewTextObj(document(), "TimesNewRomanBold", 15.0f);
Nicolas Penab3161852017-05-02 14:12:50 -04002293 EXPECT_TRUE(text_object2);
Lei Zhangf0f67682019-04-08 17:03:21 +00002294 ScopedFPDFWideString text2 =
Nicolas Penab3161852017-05-02 14:12:50 -04002295 GetFPDFWideString(L"Hi, I'm Bold. Times New Roman Bold.");
2296 EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
2297 FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 100, 600);
Lei Zhang8496d132021-07-08 04:34:34 +00002298 FPDFPage_InsertObject(page.get(), text_object2);
2299 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002300 {
Lei Zhang8496d132021-07-08 04:34:34 +00002301 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002302#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2303 static constexpr char md5[] = "285cf09ca5600fc4ec061dc5ad5c6400";
Nicolas Pena49058402017-02-14 18:26:20 -05002304#else
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002305#if defined(OS_WIN)
Hui Yingst282f0b82021-08-30 22:59:52 +00002306 static constexpr char md5[] = "5f8228bda9b4289240112a93eae1c2fb";
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002307#elif defined(OS_APPLE)
2308 static constexpr char md5[] = "26a516d923b0a18fbea0a24e3aca5562";
2309#else
Hui Yingst282f0b82021-08-30 22:59:52 +00002310 static constexpr char md5[] = "ad25881ed8ea4f0e3b22963a7beeda51";
Nicolas Pena5bcd9a32017-03-22 11:04:35 -04002311#endif
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002312#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Lei Zhange039bab2019-03-18 19:57:56 +00002313 CompareBitmap(page_bitmap.get(), 612, 792, md5);
2314
2315 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2316 VerifySavedDocument(612, 792, md5);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002317 }
Nicolas Pena49058402017-02-14 18:26:20 -05002318
2319 // And some randomly transformed text
Nicolas Penab3161852017-05-02 14:12:50 -04002320 FPDF_PAGEOBJECT text_object3 =
Nicolas Penad03ca422017-03-06 13:54:33 -05002321 FPDFPageObj_NewTextObj(document(), "Courier-Bold", 20.0f);
Nicolas Penab3161852017-05-02 14:12:50 -04002322 EXPECT_TRUE(text_object3);
Lei Zhangf0f67682019-04-08 17:03:21 +00002323 ScopedFPDFWideString text3 = GetFPDFWideString(L"Can you read me? <:)>");
Nicolas Penab3161852017-05-02 14:12:50 -04002324 EXPECT_TRUE(FPDFText_SetText(text_object3, text3.get()));
2325 FPDFPageObj_Transform(text_object3, 1, 1.5, 2, 0.5, 200, 200);
Lei Zhang8496d132021-07-08 04:34:34 +00002326 FPDFPage_InsertObject(page.get(), text_object3);
2327 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002328 {
Lei Zhang8496d132021-07-08 04:34:34 +00002329 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002330#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002331 static constexpr char md5[] = "177285dd8cdaf476683173fce64034ea";
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002332#else
2333#if defined(OS_WIN)
Hui Yingst282f0b82021-08-30 22:59:52 +00002334 static constexpr char md5[] = "8838d0af7eb87b6930c16941f2eeec81";
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002335#elif defined(OS_APPLE)
2336 static constexpr char md5[] = "532024c9ded47843313bb64a060118f3";
2337#else
Hui Yingst282f0b82021-08-30 22:59:52 +00002338 static constexpr char md5[] = "ca120ec6aeabfe96934e103890811ffc";
Nicolas Pena5bcd9a32017-03-22 11:04:35 -04002339#endif
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002340#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Lei Zhange039bab2019-03-18 19:57:56 +00002341 CompareBitmap(page_bitmap.get(), 612, 792, md5);
2342
2343 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2344 VerifySavedDocument(612, 792, md5);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002345 }
Nicolas Pena49058402017-02-14 18:26:20 -05002346
Lei Zhang8da98232019-12-11 23:29:33 +00002347 FS_MATRIX matrix;
Lei Zhangc8601bf2021-06-29 23:19:27 +00002348 EXPECT_TRUE(FPDFPageObj_GetMatrix(text_object3, &matrix));
Lei Zhang8da98232019-12-11 23:29:33 +00002349 EXPECT_FLOAT_EQ(1.0f, matrix.a);
2350 EXPECT_FLOAT_EQ(1.5f, matrix.b);
2351 EXPECT_FLOAT_EQ(2.0f, matrix.c);
2352 EXPECT_FLOAT_EQ(0.5f, matrix.d);
2353 EXPECT_FLOAT_EQ(200.0f, matrix.e);
2354 EXPECT_FLOAT_EQ(200.0f, matrix.f);
Miklos Vajnac765d2a2018-06-19 15:45:42 +00002355
Miklos Vajnad6d7ca72021-06-22 16:27:21 +00002356 EXPECT_FALSE(FPDFTextObj_GetFontSize(nullptr, nullptr));
Lei Zhang8496d132021-07-08 04:34:34 +00002357 float size = 55;
2358 EXPECT_FALSE(FPDFTextObj_GetFontSize(nullptr, &size));
2359 EXPECT_EQ(55, size);
Miklos Vajnad6d7ca72021-06-22 16:27:21 +00002360 EXPECT_TRUE(FPDFTextObj_GetFontSize(text_object3, &size));
2361 EXPECT_EQ(20, size);
Miklos Vajna8625d3b2018-06-26 15:12:48 +00002362
Nicolas Pena49058402017-02-14 18:26:20 -05002363 // TODO(npm): Why are there issues with text rotated by 90 degrees?
2364 // TODO(npm): FPDF_SaveAsCopy not giving the desired result after this.
Nicolas Pena49058402017-02-14 18:26:20 -05002365}
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002366
Lei Zhang20c52152021-06-18 20:37:10 +00002367TEST_F(FPDFEditEmbedderTest, AddStandardFontTextOfSizeZero) {
2368 // Start with a blank page
2369 ScopedFPDFPage page(FPDFPage_New(CreateNewDocument(), 0, 612, 792));
2370
2371 // Add some text of size 0 to the page.
2372 FPDF_PAGEOBJECT text_object =
2373 FPDFPageObj_NewTextObj(document(), "Arial", 0.0f);
2374 EXPECT_TRUE(text_object);
2375 ScopedFPDFWideString text = GetFPDFWideString(kBottomText);
2376 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2377 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 20, 20);
2378
Miklos Vajnad6d7ca72021-06-22 16:27:21 +00002379 float size = -1; // Make sure 'size' gets changed.
2380 EXPECT_TRUE(FPDFTextObj_GetFontSize(text_object, &size));
2381 EXPECT_EQ(0.0f, size);
Lei Zhang20c52152021-06-18 20:37:10 +00002382
2383 FPDFPage_InsertObject(page.get(), text_object);
2384 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
2385 {
2386 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
2387 CompareBitmap(page_bitmap.get(), 612, 792,
2388 pdfium::kBlankPage612By792Checksum);
2389
2390 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2391 VerifySavedDocument(612, 792, pdfium::kBlankPage612By792Checksum);
2392 }
2393}
2394
Daniel Hosseinian8cb6a652019-12-18 00:50:41 +00002395TEST_F(FPDFEditEmbedderTest, GetTextRenderMode) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002396 ASSERT_TRUE(OpenDocument("text_render_mode.pdf"));
Miklos Vajna1448cc12018-07-03 13:52:33 +00002397 FPDF_PAGE page = LoadPage(0);
2398 ASSERT_TRUE(page);
2399 ASSERT_EQ(2, FPDFPage_CountObjects(page));
2400
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002401 EXPECT_EQ(FPDF_TEXTRENDERMODE_UNKNOWN,
Daniel Hosseinian8cb6a652019-12-18 00:50:41 +00002402 FPDFTextObj_GetTextRenderMode(nullptr));
Miklos Vajna1448cc12018-07-03 13:52:33 +00002403
2404 FPDF_PAGEOBJECT fill = FPDFPage_GetObject(page, 0);
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002405 EXPECT_EQ(FPDF_TEXTRENDERMODE_FILL, FPDFTextObj_GetTextRenderMode(fill));
Miklos Vajna1448cc12018-07-03 13:52:33 +00002406
2407 FPDF_PAGEOBJECT stroke = FPDFPage_GetObject(page, 1);
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002408 EXPECT_EQ(FPDF_TEXTRENDERMODE_STROKE, FPDFTextObj_GetTextRenderMode(stroke));
2409
2410 UnloadPage(page);
2411}
2412
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002413TEST_F(FPDFEditEmbedderTest, SetTextRenderMode) {
Hui Yingst609f7d62020-04-23 23:14:13 +00002414#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002415 const char kOriginalChecksum[] = "4960c720a6cdb7b2b16be809cce58aff";
2416 const char kStrokeChecksum[] = "4c099cf9abc1565806bd7cd1cca5ac1a";
Hui Yingst609f7d62020-04-23 23:14:13 +00002417#else
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002418#if defined(OS_WIN)
2419 const char kOriginalChecksum[] = "de6e86bad3e9fda753a8471a45cfbb58";
2420#elif defined(OS_APPLE)
2421 const char kOriginalChecksum[] = "2453a9a524ee3f5f525dd21345ec4d81";
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002422#else
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002423 const char kOriginalChecksum[] = "5a012d2920ac075c39ffa9437ea42faa";
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002424#endif
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002425 const char kStrokeChecksum[] = "412e52e621b46bd77baf2162e1fb1a1d";
2426#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002427
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002428 {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002429 ASSERT_TRUE(OpenDocument("text_render_mode.pdf"));
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002430 FPDF_PAGE page = LoadPage(0);
2431 ASSERT_TRUE(page);
2432 ASSERT_EQ(2, FPDFPage_CountObjects(page));
2433
2434 // Check the bitmap
2435 {
2436 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002437 CompareBitmap(page_bitmap.get(), 612, 446, kOriginalChecksum);
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002438 }
2439
2440 // Cannot set on a null object.
2441 EXPECT_FALSE(
2442 FPDFTextObj_SetTextRenderMode(nullptr, FPDF_TEXTRENDERMODE_UNKNOWN));
2443 EXPECT_FALSE(
2444 FPDFTextObj_SetTextRenderMode(nullptr, FPDF_TEXTRENDERMODE_INVISIBLE));
2445
2446 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
2447 ASSERT_TRUE(page_object);
2448 EXPECT_EQ(FPDF_TEXTRENDERMODE_FILL,
2449 FPDFTextObj_GetTextRenderMode(page_object));
2450
2451 // Cannot set UNKNOWN as a render mode.
2452 EXPECT_FALSE(FPDFTextObj_SetTextRenderMode(page_object,
2453 FPDF_TEXTRENDERMODE_UNKNOWN));
2454
2455 EXPECT_TRUE(
2456 FPDFTextObj_SetTextRenderMode(page_object, FPDF_TEXTRENDERMODE_STROKE));
2457 EXPECT_EQ(FPDF_TEXTRENDERMODE_STROKE,
2458 FPDFTextObj_GetTextRenderMode(page_object));
2459
2460 // Check that bitmap displays changed content
2461 {
2462 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002463 CompareBitmap(page_bitmap.get(), 612, 446, kStrokeChecksum);
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002464 }
2465
Daniel Hosseinianafd27502020-07-01 04:59:03 +00002466 // Save a copy.
2467 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2468 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2469
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002470 UnloadPage(page);
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002471 }
Miklos Vajna1448cc12018-07-03 13:52:33 +00002472
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002473 {
Daniel Hosseinianafd27502020-07-01 04:59:03 +00002474 // Open the saved copy and render it. Check that the changed text render
2475 // mode is kept in the saved copy.
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002476 ASSERT_TRUE(OpenSavedDocument());
2477 FPDF_PAGE saved_page = LoadSavedPage(0);
2478 ASSERT_TRUE(saved_page);
2479
2480 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(saved_page, 0);
2481 EXPECT_TRUE(page_object);
Daniel Hosseinianafd27502020-07-01 04:59:03 +00002482 EXPECT_EQ(FPDF_TEXTRENDERMODE_STROKE,
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002483 FPDFTextObj_GetTextRenderMode(page_object));
2484
2485 ScopedFPDFBitmap bitmap = RenderSavedPage(saved_page);
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002486 CompareBitmap(bitmap.get(), 612, 446, kStrokeChecksum);
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002487
2488 CloseSavedPage(saved_page);
2489 CloseSavedDocument();
2490 }
Miklos Vajna1448cc12018-07-03 13:52:33 +00002491}
2492
Robert Collyer68a18a02021-09-14 01:48:22 +00002493TEST_F(FPDFEditEmbedderTest, TextFontProperties) {
2494 // bad object tests
2495 EXPECT_FALSE(FPDFTextObj_GetFont(nullptr));
2496 EXPECT_EQ(0U, FPDFFont_GetFontName(nullptr, nullptr, 5));
2497 EXPECT_EQ(-1, FPDFFont_GetFlags(nullptr));
2498 EXPECT_EQ(-1, FPDFFont_GetWeight(nullptr));
2499 EXPECT_FALSE(FPDFFont_GetItalicAngle(nullptr, nullptr));
2500 EXPECT_FALSE(FPDFFont_GetAscent(nullptr, 12.f, nullptr));
2501 EXPECT_FALSE(FPDFFont_GetDescent(nullptr, 12.f, nullptr));
2502 EXPECT_FALSE(FPDFFont_GetGlyphWidth(nullptr, 's', 12.f, nullptr));
2503 EXPECT_FALSE(FPDFFont_GetGlyphPath(nullptr, 's', 12.f));
2504
2505 // good object tests
2506 ASSERT_TRUE(OpenDocument("text_font.pdf"));
2507 FPDF_PAGE page = LoadPage(0);
2508 ASSERT_TRUE(page);
2509 ASSERT_EQ(1, FPDFPage_CountObjects(page));
2510 FPDF_PAGEOBJECT text = FPDFPage_GetObject(page, 0);
2511 ASSERT_TRUE(text);
2512 float font_size;
2513 ASSERT_TRUE(FPDFTextObj_GetFontSize(text, &font_size));
2514 FPDF_FONT font = FPDFTextObj_GetFont(text);
2515 ASSERT_TRUE(font);
2516
2517 // null return pointer tests
2518 EXPECT_FALSE(FPDFFont_GetItalicAngle(font, nullptr));
2519 EXPECT_FALSE(FPDFFont_GetAscent(font, font_size, nullptr));
2520 EXPECT_FALSE(FPDFFont_GetDescent(font, font_size, nullptr));
2521 EXPECT_FALSE(FPDFFont_GetGlyphWidth(font, 's', font_size, nullptr));
2522
2523 // correct property tests
2524 {
2525 EXPECT_EQ(4, FPDFFont_GetFlags(font));
2526 EXPECT_EQ(400, FPDFFont_GetWeight(font));
2527
2528 int angle;
2529 EXPECT_TRUE(FPDFFont_GetItalicAngle(font, &angle));
2530 EXPECT_EQ(0, angle);
2531
2532 float ascent;
2533 EXPECT_TRUE(FPDFFont_GetAscent(font, font_size, &ascent));
2534 EXPECT_FLOAT_EQ(891 * font_size / 1000.0f, ascent);
2535
2536 float descent;
2537 EXPECT_TRUE(FPDFFont_GetDescent(font, font_size, &descent));
2538 EXPECT_FLOAT_EQ(-216 * font_size / 1000.0f, descent);
2539
2540 float a12;
2541 float a24;
2542 EXPECT_TRUE(FPDFFont_GetGlyphWidth(font, 'a', 12.0f, &a12));
2543 EXPECT_FLOAT_EQ(a12, 5.316f);
2544 EXPECT_TRUE(FPDFFont_GetGlyphWidth(font, 'a', 24.0f, &a24));
2545 EXPECT_FLOAT_EQ(a24, 10.632f);
2546 }
2547
2548 {
2549 // FPDFFont_GetFontName() positive testing.
2550 unsigned long size = FPDFFont_GetFontName(font, nullptr, 0);
2551 const char kExpectedFontName[] = "Liberation Serif";
2552 ASSERT_EQ(sizeof(kExpectedFontName), size);
2553 std::vector<char> font_name(size);
2554 ASSERT_EQ(size, FPDFFont_GetFontName(font, font_name.data(), size));
2555 ASSERT_STREQ(kExpectedFontName, font_name.data());
2556
2557 // FPDFFont_GetFontName() negative testing.
2558 ASSERT_EQ(0U, FPDFFont_GetFontName(nullptr, nullptr, 0));
2559
2560 font_name.resize(2);
2561 font_name[0] = 'x';
2562 font_name[1] = '\0';
2563 size = FPDFFont_GetFontName(font, font_name.data(), font_name.size());
2564 ASSERT_EQ(sizeof(kExpectedFontName), size);
2565 ASSERT_STREQ("x", font_name.data());
2566 }
2567
2568 UnloadPage(page);
2569}
2570
2571TEST_F(FPDFEditEmbedderTest, GlyphPaths) {
2572 // bad glyphpath
2573 EXPECT_EQ(-1, FPDFGlyphPath_CountGlyphSegments(nullptr));
2574 EXPECT_FALSE(FPDFGlyphPath_GetGlyphPathSegment(nullptr, 1));
2575
2576 ASSERT_TRUE(OpenDocument("text_font.pdf"));
2577 FPDF_PAGE page = LoadPage(0);
2578 ASSERT_TRUE(page);
2579 ASSERT_EQ(1, FPDFPage_CountObjects(page));
2580 FPDF_PAGEOBJECT text = FPDFPage_GetObject(page, 0);
2581 ASSERT_TRUE(text);
2582 FPDF_FONT font = FPDFTextObj_GetFont(text);
2583 ASSERT_TRUE(font);
2584
2585 // good glyphpath
2586 FPDF_GLYPHPATH gpath = FPDFFont_GetGlyphPath(font, 's', 12.0f);
2587 ASSERT_TRUE(gpath);
2588
2589 int count = FPDFGlyphPath_CountGlyphSegments(gpath);
2590 ASSERT_GT(count, 0);
2591 EXPECT_FALSE(FPDFGlyphPath_GetGlyphPathSegment(gpath, -1));
2592 EXPECT_FALSE(FPDFGlyphPath_GetGlyphPathSegment(gpath, count));
2593
2594 FPDF_PATHSEGMENT segment = FPDFGlyphPath_GetGlyphPathSegment(gpath, 1);
2595 ASSERT_TRUE(segment);
2596 EXPECT_EQ(FPDF_SEGMENT_BEZIERTO, FPDFPathSegment_GetType(segment));
2597
2598 UnloadPage(page);
2599}
2600
Lei Zhang4363dab2021-06-24 19:23:09 +00002601TEST_F(FPDFEditEmbedderTest, FormGetObjects) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002602 ASSERT_TRUE(OpenDocument("form_object.pdf"));
Miklos Vajnab66077d2018-07-11 13:25:02 +00002603 FPDF_PAGE page = LoadPage(0);
2604 ASSERT_TRUE(page);
2605 ASSERT_EQ(1, FPDFPage_CountObjects(page));
2606
2607 FPDF_PAGEOBJECT form = FPDFPage_GetObject(page, 0);
Lei Zhang4363dab2021-06-24 19:23:09 +00002608 ASSERT_EQ(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(form));
Miklos Vajnab66077d2018-07-11 13:25:02 +00002609 ASSERT_EQ(-1, FPDFFormObj_CountObjects(nullptr));
2610 ASSERT_EQ(2, FPDFFormObj_CountObjects(form));
2611
Miklos Vajna1d273f12018-07-16 19:20:36 +00002612 // FPDFFormObj_GetObject() positive testing.
2613 FPDF_PAGEOBJECT text1 = FPDFFormObj_GetObject(form, 0);
2614 ASSERT_TRUE(text1);
2615 float left = 0;
2616 float bottom = 0;
2617 float right = 0;
2618 float top = 0;
2619 ASSERT_TRUE(FPDFPageObj_GetBounds(text1, &left, &bottom, &right, &top));
2620 ASSERT_EQ(271, static_cast<int>(top));
2621
2622 FPDF_PAGEOBJECT text2 = FPDFFormObj_GetObject(form, 1);
2623 ASSERT_TRUE(text2);
2624 ASSERT_TRUE(FPDFPageObj_GetBounds(text2, &left, &bottom, &right, &top));
2625 ASSERT_EQ(221, static_cast<int>(top));
2626
2627 // FPDFFormObj_GetObject() negative testing.
2628 ASSERT_EQ(nullptr, FPDFFormObj_GetObject(nullptr, 0));
2629 ASSERT_EQ(nullptr, FPDFFormObj_GetObject(form, -1));
2630 ASSERT_EQ(nullptr, FPDFFormObj_GetObject(form, 2));
2631
Lei Zhangc8601bf2021-06-29 23:19:27 +00002632 // FPDFPageObj_GetMatrix() positive testing for forms.
Lei Zhang8da98232019-12-11 23:29:33 +00002633 static constexpr FS_MATRIX kMatrix = {1.0f, 1.5f, 2.0f, 2.5f, 100.0f, 200.0f};
Lei Zhang2193da92021-06-30 01:03:07 +00002634 EXPECT_TRUE(FPDFPageObj_SetMatrix(form, &kMatrix));
Miklos Vajna46b43732018-08-14 19:15:43 +00002635
Lei Zhang8da98232019-12-11 23:29:33 +00002636 FS_MATRIX matrix;
Lei Zhangc8601bf2021-06-29 23:19:27 +00002637 EXPECT_TRUE(FPDFPageObj_GetMatrix(form, &matrix));
Lei Zhang8da98232019-12-11 23:29:33 +00002638 EXPECT_FLOAT_EQ(kMatrix.a, matrix.a);
2639 EXPECT_FLOAT_EQ(kMatrix.b, matrix.b);
2640 EXPECT_FLOAT_EQ(kMatrix.c, matrix.c);
2641 EXPECT_FLOAT_EQ(kMatrix.d, matrix.d);
2642 EXPECT_FLOAT_EQ(kMatrix.e, matrix.e);
2643 EXPECT_FLOAT_EQ(kMatrix.f, matrix.f);
Miklos Vajna46b43732018-08-14 19:15:43 +00002644
Lei Zhangc8601bf2021-06-29 23:19:27 +00002645 // FPDFPageObj_GetMatrix() negative testing for forms.
2646 EXPECT_FALSE(FPDFPageObj_GetMatrix(form, nullptr));
Miklos Vajna46b43732018-08-14 19:15:43 +00002647
Miklos Vajnab66077d2018-07-11 13:25:02 +00002648 UnloadPage(page);
2649}
2650
Lei Zhang4363dab2021-06-24 19:23:09 +00002651TEST_F(FPDFEditEmbedderTest, ModifyFormObject) {
2652#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Lei Zhang4363dab2021-06-24 19:23:09 +00002653 const char kOrigChecksum[] = "6332486c11a830d52163e453cac3f0f7";
Lei Zhang4363dab2021-06-24 19:23:09 +00002654 const char kNewChecksum[] = "9851fb1b59d91655ac8961ac89f383ae";
2655#else
2656#if defined(OS_WIN)
2657 const char kOrigChecksum[] = "9993d8fd85dfc1f9522c4e5f1533ed78";
2658 const char kNewChecksum[] = "ba6450c9060786c5aca3b7552ba7ec9e";
2659#elif defined(OS_APPLE)
2660 const char kOrigChecksum[] = "98c13e90ec592eea79b6458c0ca2822b";
2661 const char kNewChecksum[] = "8cbad8c9281e1f3bac2306a5beb1fdcd";
2662#else
2663 const char kOrigChecksum[] = "26e65fb47da5674d1b7284932c3c94d6";
2664 const char kNewChecksum[] = "fd408e99373b275316f7816ae8d35842";
2665#endif // defined(OS_WIN)
2666#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2667
2668 ASSERT_TRUE(OpenDocument("form_object.pdf"));
2669 FPDF_PAGE page = LoadPage(0);
2670 ASSERT_TRUE(page);
2671 ASSERT_EQ(1, FPDFPage_CountObjects(page));
2672
2673 {
2674 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
2675 CompareBitmap(bitmap.get(), 62, 69, kOrigChecksum);
2676 }
2677
2678 FPDF_PAGEOBJECT form = FPDFPage_GetObject(page, 0);
2679 ASSERT_EQ(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(form));
2680
Lei Zhang651113b2021-06-25 20:03:25 +00002681 FPDFPageObj_Transform(form, 0.5, 0, 0, 0.5, 0, 0);
Lei Zhang4363dab2021-06-24 19:23:09 +00002682 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2683
2684 {
2685 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
2686 CompareBitmap(bitmap.get(), 62, 69, kNewChecksum);
2687 }
2688
Lei Zhang4363dab2021-06-24 19:23:09 +00002689 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhangac7f0e12021-06-24 19:38:00 +00002690 VerifySavedDocument(62, 69, kNewChecksum);
Lei Zhang4363dab2021-06-24 19:23:09 +00002691
2692 UnloadPage(page);
2693}
2694
Nicolas Pena4c48b102018-06-13 18:23:46 +00002695// Tests adding text from standard font using FPDFText_LoadStandardFont.
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002696TEST_F(FPDFEditEmbedderTest, AddStandardFontText2) {
Nicolas Pena4c48b102018-06-13 18:23:46 +00002697 // Start with a blank page
2698 ScopedFPDFPage page(FPDFPage_New(CreateNewDocument(), 0, 612, 792));
2699
2700 // Load a standard font.
Tom Sepezffff6c52019-07-30 21:56:19 +00002701 ScopedFPDFFont font(FPDFText_LoadStandardFont(document(), "Helvetica"));
Nicolas Pena4c48b102018-06-13 18:23:46 +00002702 ASSERT_TRUE(font);
2703
2704 // Add some text to the page.
2705 FPDF_PAGEOBJECT text_object =
Tom Sepezffff6c52019-07-30 21:56:19 +00002706 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
Nicolas Pena4c48b102018-06-13 18:23:46 +00002707 EXPECT_TRUE(text_object);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002708 ScopedFPDFWideString text = GetFPDFWideString(kBottomText);
Nicolas Pena4c48b102018-06-13 18:23:46 +00002709 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2710 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 20, 20);
2711 FPDFPage_InsertObject(page.get(), text_object);
Lei Zhang30ff2532019-01-31 21:37:55 +00002712 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
Hui Yingst3b6136a2020-06-09 00:39:33 +00002713 CompareBitmap(page_bitmap.get(), 612, 792, kBottomTextChecksum);
Nicolas Pena4c48b102018-06-13 18:23:46 +00002714}
2715
Lei Zhangab41f252018-12-23 03:10:50 +00002716TEST_F(FPDFEditEmbedderTest, LoadStandardFonts) {
Nicolas Pena4c48b102018-06-13 18:23:46 +00002717 CreateNewDocument();
Lei Zhang590f4242019-05-15 20:57:26 +00002718 static constexpr const char* kStandardFontNames[] = {
Lei Zhangd72fd582018-07-27 19:37:27 +00002719 "Arial",
2720 "Arial-Bold",
2721 "Arial-BoldItalic",
2722 "Arial-Italic",
2723 "Courier",
2724 "Courier-BoldOblique",
2725 "Courier-Oblique",
2726 "Courier-Bold",
2727 "CourierNew",
2728 "CourierNew-Bold",
2729 "CourierNew-BoldItalic",
2730 "CourierNew-Italic",
2731 "Helvetica",
2732 "Helvetica-Bold",
2733 "Helvetica-BoldOblique",
2734 "Helvetica-Oblique",
2735 "Symbol",
2736 "TimesNewRoman",
2737 "TimesNewRoman-Bold",
2738 "TimesNewRoman-BoldItalic",
2739 "TimesNewRoman-Italic",
2740 "ZapfDingbats"};
Lei Zhang590f4242019-05-15 20:57:26 +00002741 for (const char* font_name : kStandardFontNames) {
Tom Sepezffff6c52019-07-30 21:56:19 +00002742 ScopedFPDFFont font(FPDFText_LoadStandardFont(document(), font_name));
Nicolas Pena4c48b102018-06-13 18:23:46 +00002743 EXPECT_TRUE(font) << font_name << " should be considered a standard font.";
2744 }
Lei Zhang590f4242019-05-15 20:57:26 +00002745 static constexpr const char* kNotStandardFontNames[] = {
Nicolas Pena4c48b102018-06-13 18:23:46 +00002746 "Abcdefg", "ArialB", "Arial-Style",
2747 "Font Name", "FontArial", "NotAStandardFontName",
2748 "TestFontName", "Quack", "Symbol-Italic",
2749 "Zapf"};
Lei Zhang590f4242019-05-15 20:57:26 +00002750 for (const char* font_name : kNotStandardFontNames) {
Tom Sepezffff6c52019-07-30 21:56:19 +00002751 ScopedFPDFFont font(FPDFText_LoadStandardFont(document(), font_name));
Nicolas Pena4c48b102018-06-13 18:23:46 +00002752 EXPECT_FALSE(font) << font_name
2753 << " should not be considered a standard font.";
2754 }
2755}
2756
Lei Zhangab41f252018-12-23 03:10:50 +00002757TEST_F(FPDFEditEmbedderTest, GraphicsData) {
Nicolas Pena603a31d2017-06-14 11:41:18 -04002758 // New page
Tom Sepeze08d2b12018-04-25 18:49:32 +00002759 ScopedFPDFPage page(FPDFPage_New(CreateNewDocument(), 0, 612, 792));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002760
2761 // Create a rect with nontrivial graphics
2762 FPDF_PAGEOBJECT rect1 = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
2763 FPDFPageObj_SetBlendMode(rect1, "Color");
2764 FPDFPage_InsertObject(page.get(), rect1);
2765 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
2766
2767 // Check that the ExtGState was created
Lei Zhang107fa7b2018-02-09 21:48:15 +00002768 CPDF_Page* cpage = CPDFPageFromFPDFPage(page.get());
Tom Sepezc8155092021-04-26 23:37:42 +00002769 const CPDF_Dictionary* graphics_dict =
2770 cpage->GetResources()->GetDictFor("ExtGState");
Nicolas Pena603a31d2017-06-14 11:41:18 -04002771 ASSERT_TRUE(graphics_dict);
Lei Zhangf40380f2018-10-12 18:31:51 +00002772 EXPECT_EQ(2u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002773
2774 // Add a text object causing no change to the graphics dictionary
2775 FPDF_PAGEOBJECT text1 = FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
2776 // Only alpha, the last component, matters for the graphics dictionary. And
2777 // the default value is 255.
Lei Zhang3475b482019-05-13 18:30:57 +00002778 EXPECT_TRUE(FPDFPageObj_SetFillColor(text1, 100, 100, 100, 255));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002779 FPDFPage_InsertObject(page.get(), text1);
2780 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002781 EXPECT_EQ(2u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002782
2783 // Add a text object increasing the size of the graphics dictionary
2784 FPDF_PAGEOBJECT text2 =
2785 FPDFPageObj_NewTextObj(document(), "Times-Roman", 12.0f);
2786 FPDFPage_InsertObject(page.get(), text2);
2787 FPDFPageObj_SetBlendMode(text2, "Darken");
Lei Zhang3475b482019-05-13 18:30:57 +00002788 EXPECT_TRUE(FPDFPageObj_SetFillColor(text2, 0, 0, 255, 150));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002789 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002790 EXPECT_EQ(3u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002791
2792 // Add a path that should reuse graphics
Nicolas Penace67be42017-06-14 14:52:49 -04002793 FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(400, 100);
Nicolas Pena603a31d2017-06-14 11:41:18 -04002794 FPDFPageObj_SetBlendMode(path, "Darken");
Lei Zhang3475b482019-05-13 18:30:57 +00002795 EXPECT_TRUE(FPDFPageObj_SetFillColor(path, 200, 200, 100, 150));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002796 FPDFPage_InsertObject(page.get(), path);
2797 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002798 EXPECT_EQ(3u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002799
2800 // Add a rect increasing the size of the graphics dictionary
2801 FPDF_PAGEOBJECT rect2 = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
2802 FPDFPageObj_SetBlendMode(rect2, "Darken");
Lei Zhang3475b482019-05-13 18:30:57 +00002803 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect2, 0, 0, 255, 150));
2804 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(rect2, 0, 0, 0, 200));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002805 FPDFPage_InsertObject(page.get(), rect2);
2806 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002807 EXPECT_EQ(4u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002808}
2809
Lei Zhangab41f252018-12-23 03:10:50 +00002810TEST_F(FPDFEditEmbedderTest, DoubleGenerating) {
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002811 // Start with a blank page
Nicolas Penad03ca422017-03-06 13:54:33 -05002812 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002813
2814 // Add a red rectangle with some non-default alpha
2815 FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
Lei Zhang3475b482019-05-13 18:30:57 +00002816 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect, 255, 0, 0, 128));
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002817 EXPECT_TRUE(FPDFPath_SetDrawMode(rect, FPDF_FILLMODE_WINDING, 0));
2818 FPDFPage_InsertObject(page, rect);
2819 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2820
2821 // Check the ExtGState
Lei Zhang107fa7b2018-02-09 21:48:15 +00002822 CPDF_Page* cpage = CPDFPageFromFPDFPage(page);
Tom Sepezc8155092021-04-26 23:37:42 +00002823 const CPDF_Dictionary* graphics_dict =
2824 cpage->GetResources()->GetDictFor("ExtGState");
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002825 ASSERT_TRUE(graphics_dict);
Lei Zhangf40380f2018-10-12 18:31:51 +00002826 EXPECT_EQ(2u, graphics_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002827
2828 // Check the bitmap
Lei Zhang107fa7b2018-02-09 21:48:15 +00002829 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002830 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002831 CompareBitmap(page_bitmap.get(), 612, 792,
2832 "5384da3406d62360ffb5cac4476fff1c");
2833 }
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002834
2835 // Never mind, my new favorite color is blue, increase alpha
Lei Zhang3475b482019-05-13 18:30:57 +00002836 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect, 0, 0, 255, 180));
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002837 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhangf40380f2018-10-12 18:31:51 +00002838 EXPECT_EQ(3u, graphics_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002839
2840 // Check that bitmap displays changed content
Lei Zhang107fa7b2018-02-09 21:48:15 +00002841 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002842 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002843 CompareBitmap(page_bitmap.get(), 612, 792,
2844 "2e51656f5073b0bee611d9cd086aa09c");
2845 }
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002846
2847 // And now generate, without changes
2848 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhangf40380f2018-10-12 18:31:51 +00002849 EXPECT_EQ(3u, graphics_dict->size());
Lei Zhang107fa7b2018-02-09 21:48:15 +00002850 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002851 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002852 CompareBitmap(page_bitmap.get(), 612, 792,
2853 "2e51656f5073b0bee611d9cd086aa09c");
2854 }
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002855
2856 // Add some text to the page
Nicolas Penab3161852017-05-02 14:12:50 -04002857 FPDF_PAGEOBJECT text_object =
2858 FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
Lei Zhangf0f67682019-04-08 17:03:21 +00002859 ScopedFPDFWideString text =
Nicolas Penab3161852017-05-02 14:12:50 -04002860 GetFPDFWideString(L"Something something #text# something");
2861 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2862 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 300, 300);
2863 FPDFPage_InsertObject(page, text_object);
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002864 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Tom Sepezc8155092021-04-26 23:37:42 +00002865 const CPDF_Dictionary* font_dict = cpage->GetResources()->GetDictFor("Font");
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002866 ASSERT_TRUE(font_dict);
Lei Zhangf40380f2018-10-12 18:31:51 +00002867 EXPECT_EQ(1u, font_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002868
2869 // Generate yet again, check dicts are reasonably sized
2870 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhangf40380f2018-10-12 18:31:51 +00002871 EXPECT_EQ(3u, graphics_dict->size());
2872 EXPECT_EQ(1u, font_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002873 FPDF_ClosePage(page);
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002874}
Nicolas Penabe90aae2017-02-27 10:41:41 -05002875
Lei Zhangab41f252018-12-23 03:10:50 +00002876TEST_F(FPDFEditEmbedderTest, LoadSimpleType1Font) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002877 CreateNewDocument();
2878 // TODO(npm): use other fonts after disallowing loading any font as any type
Tom Sepezffff6c52019-07-30 21:56:19 +00002879 RetainPtr<CPDF_Font> stock_font =
Nicolas Penad03ca422017-03-06 13:54:33 -05002880 CPDF_Font::GetStockFont(cpdf_doc(), "Times-Bold");
Tom Sepez20c41a52018-08-29 23:53:53 +00002881 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2882 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2883 FPDF_FONT_TYPE1, false));
Nicolas Penab3161852017-05-02 14:12:50 -04002884 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002885 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002886 EXPECT_TRUE(typed_font->IsType1Font());
Nicolas Penabe90aae2017-02-27 10:41:41 -05002887
Lei Zhang710fa992018-05-25 16:24:48 +00002888 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002889 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2890 EXPECT_EQ("Type1", font_dict->GetNameFor("Subtype"));
2891 EXPECT_EQ("TimesNewRomanPS-BoldMT", font_dict->GetNameFor("BaseFont"));
Nicolas Penabe90aae2017-02-27 10:41:41 -05002892 ASSERT_TRUE(font_dict->KeyExist("FirstChar"));
2893 ASSERT_TRUE(font_dict->KeyExist("LastChar"));
2894 EXPECT_EQ(32, font_dict->GetIntegerFor("FirstChar"));
Nicolas Penad03ca422017-03-06 13:54:33 -05002895 EXPECT_EQ(255, font_dict->GetIntegerFor("LastChar"));
2896
Lei Zhangde579ab2018-05-25 21:49:49 +00002897 const CPDF_Array* widths_array = font_dict->GetArrayFor("Widths");
Nicolas Penad03ca422017-03-06 13:54:33 -05002898 ASSERT_TRUE(widths_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002899 ASSERT_EQ(224u, widths_array->size());
Nicolas Penabe90aae2017-02-27 10:41:41 -05002900 EXPECT_EQ(250, widths_array->GetNumberAt(0));
Nicolas Penad03ca422017-03-06 13:54:33 -05002901 EXPECT_EQ(569, widths_array->GetNumberAt(11));
2902 EXPECT_EQ(500, widths_array->GetNumberAt(223));
Tom Sepez20c41a52018-08-29 23:53:53 +00002903 CheckFontDescriptor(font_dict, FPDF_FONT_TYPE1, true, false, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05002904}
Nicolas Penabe90aae2017-02-27 10:41:41 -05002905
Lei Zhangab41f252018-12-23 03:10:50 +00002906TEST_F(FPDFEditEmbedderTest, LoadSimpleTrueTypeFont) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002907 CreateNewDocument();
Tom Sepezffff6c52019-07-30 21:56:19 +00002908 RetainPtr<CPDF_Font> stock_font =
2909 CPDF_Font::GetStockFont(cpdf_doc(), "Courier");
Tom Sepez20c41a52018-08-29 23:53:53 +00002910 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2911 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2912 FPDF_FONT_TRUETYPE, false));
Nicolas Penab3161852017-05-02 14:12:50 -04002913 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002914 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002915 EXPECT_TRUE(typed_font->IsTrueTypeFont());
Nicolas Penabe90aae2017-02-27 10:41:41 -05002916
Lei Zhang710fa992018-05-25 16:24:48 +00002917 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002918 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2919 EXPECT_EQ("TrueType", font_dict->GetNameFor("Subtype"));
2920 EXPECT_EQ("CourierNewPSMT", font_dict->GetNameFor("BaseFont"));
Nicolas Penad03ca422017-03-06 13:54:33 -05002921 ASSERT_TRUE(font_dict->KeyExist("FirstChar"));
2922 ASSERT_TRUE(font_dict->KeyExist("LastChar"));
2923 EXPECT_EQ(32, font_dict->GetIntegerFor("FirstChar"));
2924 EXPECT_EQ(255, font_dict->GetIntegerFor("LastChar"));
Nicolas Penabe90aae2017-02-27 10:41:41 -05002925
Lei Zhangde579ab2018-05-25 21:49:49 +00002926 const CPDF_Array* widths_array = font_dict->GetArrayFor("Widths");
Nicolas Penad03ca422017-03-06 13:54:33 -05002927 ASSERT_TRUE(widths_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002928 ASSERT_EQ(224u, widths_array->size());
Nicolas Penad03ca422017-03-06 13:54:33 -05002929 EXPECT_EQ(600, widths_array->GetNumberAt(33));
2930 EXPECT_EQ(600, widths_array->GetNumberAt(74));
2931 EXPECT_EQ(600, widths_array->GetNumberAt(223));
Tom Sepez20c41a52018-08-29 23:53:53 +00002932 CheckFontDescriptor(font_dict, FPDF_FONT_TRUETYPE, false, false, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05002933}
2934
Lei Zhangab41f252018-12-23 03:10:50 +00002935TEST_F(FPDFEditEmbedderTest, LoadCIDType0Font) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002936 CreateNewDocument();
Tom Sepezffff6c52019-07-30 21:56:19 +00002937 RetainPtr<CPDF_Font> stock_font =
Nicolas Penad03ca422017-03-06 13:54:33 -05002938 CPDF_Font::GetStockFont(cpdf_doc(), "Times-Roman");
Tom Sepez20c41a52018-08-29 23:53:53 +00002939 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2940 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2941 FPDF_FONT_TYPE1, 1));
Nicolas Penab3161852017-05-02 14:12:50 -04002942 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002943 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002944 EXPECT_TRUE(typed_font->IsCIDFont());
2945
2946 // Check font dictionary entries
Lei Zhang710fa992018-05-25 16:24:48 +00002947 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002948 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2949 EXPECT_EQ("Type0", font_dict->GetNameFor("Subtype"));
2950 EXPECT_EQ("TimesNewRomanPSMT-Identity-H", font_dict->GetNameFor("BaseFont"));
2951 EXPECT_EQ("Identity-H", font_dict->GetNameFor("Encoding"));
Lei Zhangde579ab2018-05-25 21:49:49 +00002952 const CPDF_Array* descendant_array =
2953 font_dict->GetArrayFor("DescendantFonts");
Nicolas Penad03ca422017-03-06 13:54:33 -05002954 ASSERT_TRUE(descendant_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002955 EXPECT_EQ(1u, descendant_array->size());
Nicolas Penad03ca422017-03-06 13:54:33 -05002956
2957 // Check the CIDFontDict
Lei Zhangde579ab2018-05-25 21:49:49 +00002958 const CPDF_Dictionary* cidfont_dict = descendant_array->GetDictAt(0);
Lei Zhanga228ff32020-06-24 17:39:33 +00002959 EXPECT_EQ("Font", cidfont_dict->GetNameFor("Type"));
2960 EXPECT_EQ("CIDFontType0", cidfont_dict->GetNameFor("Subtype"));
2961 EXPECT_EQ("TimesNewRomanPSMT", cidfont_dict->GetNameFor("BaseFont"));
Lei Zhangb1ec2802018-05-25 21:55:24 +00002962 const CPDF_Dictionary* cidinfo_dict =
2963 cidfont_dict->GetDictFor("CIDSystemInfo");
Nicolas Penad03ca422017-03-06 13:54:33 -05002964 ASSERT_TRUE(cidinfo_dict);
Lei Zhang9c950b12019-01-16 19:06:37 +00002965 const CPDF_Object* registry = cidinfo_dict->GetObjectFor("Registry");
2966 ASSERT_TRUE(registry);
KDr28da0e1b2019-01-17 03:44:29 +00002967 EXPECT_EQ(CPDF_Object::kString, registry->GetType());
Lei Zhang9c950b12019-01-16 19:06:37 +00002968 EXPECT_EQ("Adobe", registry->GetString());
2969 const CPDF_Object* ordering = cidinfo_dict->GetObjectFor("Ordering");
2970 ASSERT_TRUE(ordering);
KDr28da0e1b2019-01-17 03:44:29 +00002971 EXPECT_EQ(CPDF_Object::kString, ordering->GetType());
Lei Zhang9c950b12019-01-16 19:06:37 +00002972 EXPECT_EQ("Identity", ordering->GetString());
Nicolas Penad03ca422017-03-06 13:54:33 -05002973 EXPECT_EQ(0, cidinfo_dict->GetNumberFor("Supplement"));
Tom Sepez20c41a52018-08-29 23:53:53 +00002974 CheckFontDescriptor(cidfont_dict, FPDF_FONT_TYPE1, false, false, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05002975
2976 // Check widths
Lei Zhangde579ab2018-05-25 21:49:49 +00002977 const CPDF_Array* widths_array = cidfont_dict->GetArrayFor("W");
Nicolas Penad03ca422017-03-06 13:54:33 -05002978 ASSERT_TRUE(widths_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002979 EXPECT_GT(widths_array->size(), 1u);
Nicolas Penad03ca422017-03-06 13:54:33 -05002980 CheckCompositeFontWidths(widths_array, typed_font);
2981}
2982
Lei Zhangab41f252018-12-23 03:10:50 +00002983TEST_F(FPDFEditEmbedderTest, LoadCIDType2Font) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002984 CreateNewDocument();
Tom Sepezffff6c52019-07-30 21:56:19 +00002985 RetainPtr<CPDF_Font> stock_font =
Nicolas Penad03ca422017-03-06 13:54:33 -05002986 CPDF_Font::GetStockFont(cpdf_doc(), "Helvetica-Oblique");
Tom Sepez20c41a52018-08-29 23:53:53 +00002987 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2988 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2989 FPDF_FONT_TRUETYPE, 1));
Nicolas Penab3161852017-05-02 14:12:50 -04002990 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002991 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002992 EXPECT_TRUE(typed_font->IsCIDFont());
2993
2994 // Check font dictionary entries
Lei Zhang710fa992018-05-25 16:24:48 +00002995 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002996 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2997 EXPECT_EQ("Type0", font_dict->GetNameFor("Subtype"));
2998 EXPECT_EQ("Arial-ItalicMT", font_dict->GetNameFor("BaseFont"));
2999 EXPECT_EQ("Identity-H", font_dict->GetNameFor("Encoding"));
Lei Zhangde579ab2018-05-25 21:49:49 +00003000 const CPDF_Array* descendant_array =
3001 font_dict->GetArrayFor("DescendantFonts");
Nicolas Penad03ca422017-03-06 13:54:33 -05003002 ASSERT_TRUE(descendant_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00003003 EXPECT_EQ(1u, descendant_array->size());
Nicolas Penad03ca422017-03-06 13:54:33 -05003004
3005 // Check the CIDFontDict
Lei Zhangde579ab2018-05-25 21:49:49 +00003006 const CPDF_Dictionary* cidfont_dict = descendant_array->GetDictAt(0);
Lei Zhanga228ff32020-06-24 17:39:33 +00003007 EXPECT_EQ("Font", cidfont_dict->GetNameFor("Type"));
3008 EXPECT_EQ("CIDFontType2", cidfont_dict->GetNameFor("Subtype"));
3009 EXPECT_EQ("Arial-ItalicMT", cidfont_dict->GetNameFor("BaseFont"));
Lei Zhangb1ec2802018-05-25 21:55:24 +00003010 const CPDF_Dictionary* cidinfo_dict =
3011 cidfont_dict->GetDictFor("CIDSystemInfo");
Nicolas Penad03ca422017-03-06 13:54:33 -05003012 ASSERT_TRUE(cidinfo_dict);
3013 EXPECT_EQ("Adobe", cidinfo_dict->GetStringFor("Registry"));
3014 EXPECT_EQ("Identity", cidinfo_dict->GetStringFor("Ordering"));
3015 EXPECT_EQ(0, cidinfo_dict->GetNumberFor("Supplement"));
Tom Sepez20c41a52018-08-29 23:53:53 +00003016 CheckFontDescriptor(cidfont_dict, FPDF_FONT_TRUETYPE, false, true, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05003017
3018 // Check widths
Lei Zhangde579ab2018-05-25 21:49:49 +00003019 const CPDF_Array* widths_array = cidfont_dict->GetArrayFor("W");
Nicolas Penad03ca422017-03-06 13:54:33 -05003020 ASSERT_TRUE(widths_array);
3021 CheckCompositeFontWidths(widths_array, typed_font);
Nicolas Penabe90aae2017-02-27 10:41:41 -05003022}
rbpotterce8e51e2017-04-28 12:42:47 -07003023
Lei Zhangab41f252018-12-23 03:10:50 +00003024TEST_F(FPDFEditEmbedderTest, NormalizeNegativeRotation) {
rbpotterce8e51e2017-04-28 12:42:47 -07003025 // Load document with a -90 degree rotation
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003026 ASSERT_TRUE(OpenDocument("bug_713197.pdf"));
rbpotterce8e51e2017-04-28 12:42:47 -07003027 FPDF_PAGE page = LoadPage(0);
3028 EXPECT_NE(nullptr, page);
3029
3030 EXPECT_EQ(3, FPDFPage_GetRotation(page));
3031 UnloadPage(page);
3032}
Nicolas Penab3161852017-05-02 14:12:50 -04003033
Hui Yingst9d6ec8f2020-11-05 23:35:38 +00003034TEST_F(FPDFEditEmbedderTest, AddTrueTypeFontText) {
Nicolas Penab3161852017-05-02 14:12:50 -04003035 // Start with a blank page
3036 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
3037 {
Tom Sepezffff6c52019-07-30 21:56:19 +00003038 RetainPtr<CPDF_Font> stock_font =
3039 CPDF_Font::GetStockFont(cpdf_doc(), "Arial");
Tom Sepez20c41a52018-08-29 23:53:53 +00003040 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
3041 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
3042 FPDF_FONT_TRUETYPE, 0));
Nicolas Penab3161852017-05-02 14:12:50 -04003043 ASSERT_TRUE(font.get());
3044
3045 // Add some text to the page
3046 FPDF_PAGEOBJECT text_object =
3047 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
3048 EXPECT_TRUE(text_object);
Hui Yingst3b6136a2020-06-09 00:39:33 +00003049 ScopedFPDFWideString text = GetFPDFWideString(kLoadedFontText);
Nicolas Penab3161852017-05-02 14:12:50 -04003050 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
3051 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 400, 400);
3052 FPDFPage_InsertObject(page, text_object);
Lei Zhang30ff2532019-01-31 21:37:55 +00003053 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00003054 CompareBitmap(page_bitmap.get(), 612, 792, kLoadedFontTextChecksum);
Nicolas Penab3161852017-05-02 14:12:50 -04003055
3056 // Add some more text, same font
3057 FPDF_PAGEOBJECT text_object2 =
3058 FPDFPageObj_CreateTextObj(document(), font.get(), 15.0f);
Lei Zhangf0f67682019-04-08 17:03:21 +00003059 ScopedFPDFWideString text2 = GetFPDFWideString(L"Bigger font size");
Nicolas Penab3161852017-05-02 14:12:50 -04003060 EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
3061 FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 200, 200);
3062 FPDFPage_InsertObject(page, text_object2);
Nicolas Penab3161852017-05-02 14:12:50 -04003063 }
Lei Zhang30ff2532019-01-31 21:37:55 +00003064 ScopedFPDFBitmap page_bitmap2 = RenderPage(page);
Hui Yingst9d6ec8f2020-11-05 23:35:38 +00003065#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingst9d6ec8f2020-11-05 23:35:38 +00003066 const char kInsertTrueTypeChecksum[] = "f2ee263957a5584f3c72424e8683ac8c";
Hui Yingst9d6ec8f2020-11-05 23:35:38 +00003067#else
Hui Yingst3b6136a2020-06-09 00:39:33 +00003068#if defined(OS_WIN)
3069 const char kInsertTrueTypeChecksum[] = "2199b579c49ab5f80c246a586a80ee90";
Lei Zhang0c03d632020-07-30 17:05:36 +00003070#elif defined(OS_APPLE)
Hui Yingst3b6136a2020-06-09 00:39:33 +00003071 const char kInsertTrueTypeChecksum[] = "9a1a7dfebe659513691aadd0d95b8d50";
Nicolas Penab3161852017-05-02 14:12:50 -04003072#else
Hui Yingst3b6136a2020-06-09 00:39:33 +00003073 const char kInsertTrueTypeChecksum[] = "c1d10cce1761c4a998a16b2562030568";
Lei Zhange4cdac52019-04-30 16:45:57 +00003074#endif
Hui Yingst9d6ec8f2020-11-05 23:35:38 +00003075#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingst3b6136a2020-06-09 00:39:33 +00003076 CompareBitmap(page_bitmap2.get(), 612, 792, kInsertTrueTypeChecksum);
Nicolas Penab3161852017-05-02 14:12:50 -04003077
Nicolas Pena207b7272017-05-26 17:37:06 -04003078 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Nicolas Penab3161852017-05-02 14:12:50 -04003079 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3080 FPDF_ClosePage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04003081
Hui Yingst3b6136a2020-06-09 00:39:33 +00003082 VerifySavedDocument(612, 792, kInsertTrueTypeChecksum);
Nicolas Penab3161852017-05-02 14:12:50 -04003083}
Nicolas Penaf45ade32017-05-03 10:23:49 -04003084
Lei Zhangab41f252018-12-23 03:10:50 +00003085TEST_F(FPDFEditEmbedderTest, TransformAnnot) {
Jane Liueda65252017-06-07 11:31:27 -04003086 // Open a file with one annotation and load its first page.
3087 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00003088 FPDF_PAGE page = LoadPage(0);
Jane Liueda65252017-06-07 11:31:27 -04003089 ASSERT_TRUE(page);
3090
Lei Zhanga21d5932018-02-05 18:28:38 +00003091 {
3092 // Add an underline annotation to the page without specifying its rectangle.
Tom Sepeze08d2b12018-04-25 18:49:32 +00003093 ScopedFPDFAnnotation annot(
Lei Zhanga21d5932018-02-05 18:28:38 +00003094 FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE));
3095 ASSERT_TRUE(annot);
Jane Liueda65252017-06-07 11:31:27 -04003096
Lei Zhanga21d5932018-02-05 18:28:38 +00003097 // FPDFPage_TransformAnnots() should run without errors when modifying
3098 // annotation rectangles.
3099 FPDFPage_TransformAnnots(page, 1, 2, 3, 4, 5, 6);
3100 }
Jane Liueda65252017-06-07 11:31:27 -04003101 UnloadPage(page);
3102}
3103
Nicolas Penaf45ade32017-05-03 10:23:49 -04003104// TODO(npm): Add tests using Japanese fonts in other OS.
Lei Zhangfe8e7582020-08-05 19:23:16 +00003105#if defined(OS_LINUX) || defined(OS_CHROMEOS)
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00003106TEST_F(FPDFEditEmbedderTest, AddCIDFontText) {
Nicolas Penaf45ade32017-05-03 10:23:49 -04003107 // Start with a blank page
3108 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
3109 CFX_Font CIDfont;
3110 {
3111 // First, get the data from the font
Tom Sepez6c57cda2021-07-23 19:41:57 +00003112 CIDfont.LoadSubst("IPAGothic", 1, 0, 400, 0, FX_CodePage::kShiftJIS, 0);
Nicolas Penaf45ade32017-05-03 10:23:49 -04003113 EXPECT_EQ("IPAGothic", CIDfont.GetFaceName());
Tom Sepez20c41a52018-08-29 23:53:53 +00003114 pdfium::span<const uint8_t> span = CIDfont.GetFontSpan();
Nicolas Penaf45ade32017-05-03 10:23:49 -04003115
3116 // Load the data into a FPDF_Font.
Tom Sepez20c41a52018-08-29 23:53:53 +00003117 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
3118 FPDF_FONT_TRUETYPE, 1));
Nicolas Penaf45ade32017-05-03 10:23:49 -04003119 ASSERT_TRUE(font.get());
3120
3121 // Add some text to the page
3122 FPDF_PAGEOBJECT text_object =
3123 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
3124 ASSERT_TRUE(text_object);
3125 std::wstring wstr = L"ABCDEFGhijklmnop.";
Lei Zhangf0f67682019-04-08 17:03:21 +00003126 ScopedFPDFWideString text = GetFPDFWideString(wstr);
Nicolas Penaf45ade32017-05-03 10:23:49 -04003127 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
3128 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 200, 200);
3129 FPDFPage_InsertObject(page, text_object);
3130
3131 // And add some Japanese characters
3132 FPDF_PAGEOBJECT text_object2 =
3133 FPDFPageObj_CreateTextObj(document(), font.get(), 18.0f);
3134 ASSERT_TRUE(text_object2);
3135 std::wstring wstr2 =
3136 L"\u3053\u3093\u306B\u3061\u306f\u4e16\u754C\u3002\u3053\u3053\u306B1"
3137 L"\u756A";
Lei Zhangf0f67682019-04-08 17:03:21 +00003138 ScopedFPDFWideString text2 = GetFPDFWideString(wstr2);
Nicolas Penaf45ade32017-05-03 10:23:49 -04003139 EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
3140 FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 100, 500);
3141 FPDFPage_InsertObject(page, text_object2);
3142 }
3143
Nicolas Pena207b7272017-05-26 17:37:06 -04003144 // Check that the text renders properly.
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00003145#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
3146 static constexpr char md5[] = "683eefd6c31206de23b7f709b66e6daf";
3147#else
Hui Yingst282f0b82021-08-30 22:59:52 +00003148 static constexpr char md5[] = "4d7ad0dc333fde3987b79122c00a3f2a";
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00003149#endif
Lei Zhang107fa7b2018-02-09 21:48:15 +00003150 {
Lei Zhang30ff2532019-01-31 21:37:55 +00003151 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00003152 CompareBitmap(page_bitmap.get(), 612, 792, md5);
3153 }
Nicolas Penaf45ade32017-05-03 10:23:49 -04003154
3155 // Save the document, close the page.
Nicolas Pena207b7272017-05-26 17:37:06 -04003156 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Nicolas Penaf45ade32017-05-03 10:23:49 -04003157 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3158 FPDF_ClosePage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04003159
3160 VerifySavedDocument(612, 792, md5);
Nicolas Penaf45ade32017-05-03 10:23:49 -04003161}
Lei Zhangfe8e7582020-08-05 19:23:16 +00003162#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003163
Hui Yingst29d377b2021-03-03 20:22:41 +00003164// TODO(crbug.com/pdfium/1651): Fix this issue and enable the test for Skia.
3165#if defined(_SKIA_SUPPORT_)
Lei Zhang03e5e682019-09-16 19:45:55 +00003166#define MAYBE_SaveAndRender DISABLED_SaveAndRender
3167#else
3168#define MAYBE_SaveAndRender SaveAndRender
3169#endif
3170TEST_F(FPDFEditEmbedderTest, MAYBE_SaveAndRender) {
Hui Yingst29d377b2021-03-03 20:22:41 +00003171#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
3172 static constexpr char kChecksum[] = "0e8b079e349e34f64211c495845a3529";
3173#else
3174 static constexpr char kChecksum[] = "3c20472b0552c0c22b88ab1ed8c6202b";
3175#endif
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003176 {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003177 ASSERT_TRUE(OpenDocument("bug_779.pdf"));
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003178 FPDF_PAGE page = LoadPage(0);
3179 ASSERT_NE(nullptr, page);
3180
Hui Yingst29d377b2021-03-03 20:22:41 +00003181 // Now add a more complex green path.
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003182 FPDF_PAGEOBJECT green_path = FPDFPageObj_CreateNewPath(20, 20);
Lei Zhang3475b482019-05-13 18:30:57 +00003183 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_path, 0, 255, 0, 200));
Hui Yingst29d377b2021-03-03 20:22:41 +00003184 // TODO(npm): stroking will cause the checksums to differ.
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003185 EXPECT_TRUE(FPDFPath_SetDrawMode(green_path, FPDF_FILLMODE_WINDING, 0));
3186 EXPECT_TRUE(FPDFPath_LineTo(green_path, 20, 63));
3187 EXPECT_TRUE(FPDFPath_BezierTo(green_path, 55, 55, 78, 78, 90, 90));
3188 EXPECT_TRUE(FPDFPath_LineTo(green_path, 133, 133));
3189 EXPECT_TRUE(FPDFPath_LineTo(green_path, 133, 33));
3190 EXPECT_TRUE(FPDFPath_BezierTo(green_path, 38, 33, 39, 36, 40, 40));
3191 EXPECT_TRUE(FPDFPath_Close(green_path));
3192 FPDFPage_InsertObject(page, green_path);
Tom Sepeze08d2b12018-04-25 18:49:32 +00003193 ScopedFPDFBitmap page_bitmap = RenderLoadedPage(page);
Hui Yingst29d377b2021-03-03 20:22:41 +00003194 CompareBitmap(page_bitmap.get(), 612, 792, kChecksum);
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003195
3196 // Now save the result, closing the page and document
3197 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3198 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3199 UnloadPage(page);
3200 }
Dan Sinclair04e4dc82017-10-18 12:17:14 -04003201
Hui Yingst29d377b2021-03-03 20:22:41 +00003202 VerifySavedDocument(612, 792, kChecksum);
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003203}
Jane Liu28fb7ba2017-08-02 21:45:57 -04003204
Lei Zhangab41f252018-12-23 03:10:50 +00003205TEST_F(FPDFEditEmbedderTest, AddMark) {
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003206 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003207 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003208 FPDF_PAGE page = LoadPage(0);
3209 ASSERT_TRUE(page);
3210
Lei Zhang2697cb12019-07-03 18:14:29 +00003211 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003212
3213 // Add to the first page object a "Bounds" mark with "Position": "First".
3214 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
3215 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_AddMark(page_object, "Bounds");
3216 EXPECT_TRUE(mark);
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003217 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), page_object, mark,
3218 "Position", "First"));
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003219
Lei Zhang2697cb12019-07-03 18:14:29 +00003220 CheckMarkCounts(page, 1, 19, 8, 4, 9, 2);
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003221
3222 // Save the file
3223 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3224 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3225 UnloadPage(page);
3226
3227 // Re-open the file and check the new mark is present.
Lei Zhang0b494052019-01-31 21:41:15 +00003228 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003229 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00003230 ASSERT_TRUE(saved_page);
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003231
Lei Zhang2697cb12019-07-03 18:14:29 +00003232 CheckMarkCounts(saved_page, 1, 19, 8, 4, 9, 2);
3233
3234 CloseSavedPage(saved_page);
3235 CloseSavedDocument();
3236}
3237
Hui Yingst04440af2020-07-27 22:39:02 +00003238TEST_F(FPDFEditEmbedderTest, AddMarkCompressedStream) {
Lei Zhang2697cb12019-07-03 18:14:29 +00003239 // Load document with some text in a compressed stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003240 ASSERT_TRUE(OpenDocument("hello_world_compressed_stream.pdf"));
Lei Zhang2697cb12019-07-03 18:14:29 +00003241 FPDF_PAGE page = LoadPage(0);
3242 ASSERT_TRUE(page);
3243
3244 // Render and check there are no marks.
3245 {
3246 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00003247 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Lei Zhang2697cb12019-07-03 18:14:29 +00003248 }
3249 CheckMarkCounts(page, 0, 2, 0, 0, 0, 0);
3250
3251 // Add to the first page object a "Bounds" mark with "Position": "First".
3252 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
3253 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_AddMark(page_object, "Bounds");
3254 EXPECT_TRUE(mark);
3255 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), page_object, mark,
3256 "Position", "First"));
3257
3258 // Render and check there is 1 mark.
3259 {
3260 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00003261 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Lei Zhang2697cb12019-07-03 18:14:29 +00003262 }
3263 CheckMarkCounts(page, 0, 2, 0, 0, 0, 1);
3264
3265 // Save the file.
3266 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3267 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3268 UnloadPage(page);
3269
3270 // Re-open the file and check the new mark is present.
3271 ASSERT_TRUE(OpenSavedDocument());
3272 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00003273 ASSERT_TRUE(saved_page);
Lei Zhang2697cb12019-07-03 18:14:29 +00003274
3275 {
3276 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00003277 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Lei Zhang2697cb12019-07-03 18:14:29 +00003278 }
3279 CheckMarkCounts(saved_page, 0, 2, 0, 0, 0, 1);
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003280
3281 CloseSavedPage(saved_page);
3282 CloseSavedDocument();
3283}
3284
Lei Zhangab41f252018-12-23 03:10:50 +00003285TEST_F(FPDFEditEmbedderTest, SetMarkParam) {
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003286 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003287 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003288 FPDF_PAGE page = LoadPage(0);
3289 ASSERT_TRUE(page);
3290
3291 constexpr int kExpectedObjectCount = 19;
3292 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
3293
3294 // Check the "Bounds" mark's "Position" param is "Last".
3295 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
3296 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
3297 ASSERT_TRUE(mark);
3298 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003299 unsigned long name_len = 999u;
3300 ASSERT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
3301 EXPECT_EQ((6u + 1u) * 2u, name_len);
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003302 ASSERT_EQ(L"Bounds",
3303 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3304 unsigned long out_buffer_len;
3305 ASSERT_TRUE(FPDFPageObjMark_GetParamStringValue(
3306 mark, "Position", buffer, sizeof(buffer), &out_buffer_len));
3307 ASSERT_EQ(L"Last",
3308 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3309
3310 // Set is to "End".
3311 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), page_object, mark,
3312 "Position", "End"));
3313
3314 // Verify the object passed must correspond to the mark passed.
3315 FPDF_PAGEOBJECT another_page_object = FPDFPage_GetObject(page, 17);
3316 EXPECT_FALSE(FPDFPageObjMark_SetStringParam(document(), another_page_object,
3317 mark, "Position", "End"));
3318
3319 // Verify nothing else changed.
3320 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
3321
3322 // Verify "Position" now maps to "End".
3323 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
3324 mark, "Position", buffer, sizeof(buffer), &out_buffer_len));
3325 EXPECT_EQ(L"End",
3326 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3327
3328 // Save the file
3329 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3330 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3331 UnloadPage(page);
3332
3333 // Re-open the file and cerify "Position" still maps to "End".
Lei Zhang0b494052019-01-31 21:41:15 +00003334 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003335 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00003336 ASSERT_TRUE(saved_page);
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003337
3338 CheckMarkCounts(saved_page, 1, kExpectedObjectCount, 8, 4, 9, 1);
3339 page_object = FPDFPage_GetObject(saved_page, 18);
3340 mark = FPDFPageObj_GetMark(page_object, 1);
3341 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
3342 mark, "Position", buffer, sizeof(buffer), &out_buffer_len));
3343 EXPECT_EQ(L"End",
3344 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3345
3346 CloseSavedPage(saved_page);
3347 CloseSavedDocument();
3348}
3349
Hui Yingst9d6ec8f2020-11-05 23:35:38 +00003350TEST_F(FPDFEditEmbedderTest, AddMarkedText) {
Henrique Nakashima144107d2018-07-10 21:04:05 +00003351 // Start with a blank page.
3352 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
3353
Tom Sepezffff6c52019-07-30 21:56:19 +00003354 RetainPtr<CPDF_Font> stock_font =
3355 CPDF_Font::GetStockFont(cpdf_doc(), "Arial");
Tom Sepez20c41a52018-08-29 23:53:53 +00003356 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
3357 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
3358 FPDF_FONT_TRUETYPE, 0));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003359 ASSERT_TRUE(font.get());
3360
3361 // Add some text to the page.
3362 FPDF_PAGEOBJECT text_object =
3363 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
3364
3365 EXPECT_TRUE(text_object);
Hui Yingst3b6136a2020-06-09 00:39:33 +00003366 ScopedFPDFWideString text1 = GetFPDFWideString(kLoadedFontText);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003367 EXPECT_TRUE(FPDFText_SetText(text_object, text1.get()));
3368 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 400, 400);
3369 FPDFPage_InsertObject(page, text_object);
3370
3371 // Add a mark with the tag "TestMarkName" to that text.
3372 EXPECT_EQ(0, FPDFPageObj_CountMarks(text_object));
Henrique Nakashima6fc8d872018-09-18 16:48:31 +00003373 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_AddMark(text_object, "Test Mark Name");
Henrique Nakashima144107d2018-07-10 21:04:05 +00003374 EXPECT_TRUE(mark);
3375 EXPECT_EQ(1, FPDFPageObj_CountMarks(text_object));
3376 EXPECT_EQ(mark, FPDFPageObj_GetMark(text_object, 0));
3377 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003378 unsigned long name_len = 999u;
3379 ASSERT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
3380 EXPECT_EQ((14u + 1u) * 2, name_len);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003381 std::wstring name =
3382 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
Henrique Nakashima6fc8d872018-09-18 16:48:31 +00003383 EXPECT_EQ(L"Test Mark Name", name);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003384
3385 // Add parameters:
3386 // - int "IntKey" : 42
3387 // - string "StringKey": "StringValue"
Henrique Nakashima07520f62018-07-12 19:45:29 +00003388 // - blob "BlobKey": "\x01\x02\x03\0BlobValue1\0\0\0BlobValue2\0"
Lei Zhang590f4242019-05-15 20:57:26 +00003389 constexpr size_t kBlobLen = 28;
Lei Zhangd3b028b2018-11-30 22:22:00 +00003390 char block_value[kBlobLen];
3391 memcpy(block_value, "\x01\x02\x03\0BlobValue1\0\0\0BlobValue2\0", kBlobLen);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003392 EXPECT_EQ(0, FPDFPageObjMark_CountParams(mark));
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003393 EXPECT_TRUE(
3394 FPDFPageObjMark_SetIntParam(document(), text_object, mark, "IntKey", 42));
3395 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), text_object, mark,
3396 "StringKey", "StringValue"));
3397 EXPECT_TRUE(FPDFPageObjMark_SetBlobParam(document(), text_object, mark,
Lei Zhangd3b028b2018-11-30 22:22:00 +00003398 "BlobKey", block_value, kBlobLen));
Henrique Nakashima07520f62018-07-12 19:45:29 +00003399 EXPECT_EQ(3, FPDFPageObjMark_CountParams(mark));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003400
3401 // Check the two parameters can be retrieved.
3402 EXPECT_EQ(FPDF_OBJECT_NUMBER,
Henrique Nakashima94230e52018-07-11 22:02:02 +00003403 FPDFPageObjMark_GetParamValueType(mark, "IntKey"));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003404 int int_value;
Henrique Nakashima94230e52018-07-11 22:02:02 +00003405 EXPECT_TRUE(FPDFPageObjMark_GetParamIntValue(mark, "IntKey", &int_value));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003406 EXPECT_EQ(42, int_value);
3407
3408 EXPECT_EQ(FPDF_OBJECT_STRING,
Henrique Nakashima94230e52018-07-11 22:02:02 +00003409 FPDFPageObjMark_GetParamValueType(mark, "StringKey"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003410 unsigned long out_buffer_len = 999u;
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003411 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
3412 mark, "StringKey", buffer, sizeof(buffer), &out_buffer_len));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003413 EXPECT_GT(out_buffer_len, 0u);
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003414 EXPECT_NE(999u, out_buffer_len);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003415 name = GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
3416 EXPECT_EQ(L"StringValue", name);
3417
Henrique Nakashima07520f62018-07-12 19:45:29 +00003418 EXPECT_EQ(FPDF_OBJECT_STRING,
3419 FPDFPageObjMark_GetParamValueType(mark, "BlobKey"));
3420 out_buffer_len = 0;
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003421 EXPECT_TRUE(FPDFPageObjMark_GetParamBlobValue(
3422 mark, "BlobKey", buffer, sizeof(buffer), &out_buffer_len));
Henrique Nakashima07520f62018-07-12 19:45:29 +00003423 EXPECT_EQ(kBlobLen, out_buffer_len);
Lei Zhangd3b028b2018-11-30 22:22:00 +00003424 EXPECT_EQ(0, memcmp(block_value, buffer, kBlobLen));
Henrique Nakashima07520f62018-07-12 19:45:29 +00003425
Lei Zhangf16376e2020-06-18 19:19:32 +00003426 // Render and check the bitmap is the expected one.
Henrique Nakashima144107d2018-07-10 21:04:05 +00003427 {
Lei Zhang30ff2532019-01-31 21:37:55 +00003428 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00003429 CompareBitmap(page_bitmap.get(), 612, 792, kLoadedFontTextChecksum);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003430 }
3431
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003432 // Now save the result.
3433 EXPECT_EQ(1, FPDFPage_CountObjects(page));
3434 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3435 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3436
Henrique Nakashima144107d2018-07-10 21:04:05 +00003437 FPDF_ClosePage(page);
3438
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003439 // Re-open the file and check the changes were kept in the saved .pdf.
Lei Zhang0b494052019-01-31 21:41:15 +00003440 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003441 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00003442 ASSERT_TRUE(saved_page);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003443 EXPECT_EQ(1, FPDFPage_CountObjects(saved_page));
3444
3445 text_object = FPDFPage_GetObject(saved_page, 0);
3446 EXPECT_TRUE(text_object);
3447 EXPECT_EQ(1, FPDFPageObj_CountMarks(text_object));
3448 mark = FPDFPageObj_GetMark(text_object, 0);
3449 EXPECT_TRUE(mark);
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003450
3451 name_len = 999u;
3452 ASSERT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
3453 EXPECT_EQ((14u + 1u) * 2, name_len);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003454 name = GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
Henrique Nakashima6fc8d872018-09-18 16:48:31 +00003455 EXPECT_EQ(L"Test Mark Name", name);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003456
3457 CloseSavedPage(saved_page);
3458 CloseSavedDocument();
Henrique Nakashima144107d2018-07-10 21:04:05 +00003459}
3460
Lei Zhangab41f252018-12-23 03:10:50 +00003461TEST_F(FPDFEditEmbedderTest, MarkGetName) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003462 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003463 FPDF_PAGE page = LoadPage(0);
3464 ASSERT_TRUE(page);
3465 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
3466 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
3467 ASSERT_TRUE(mark);
3468
3469 char buffer[256];
3470 unsigned long out_len;
3471
3472 // Show the positive cases of FPDFPageObjMark_GetName.
3473 out_len = 999u;
3474 EXPECT_TRUE(FPDFPageObjMark_GetName(mark, nullptr, 0, &out_len));
3475 EXPECT_EQ((6u + 1u) * 2u, out_len);
3476
3477 out_len = 999u;
3478 EXPECT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &out_len));
3479 EXPECT_EQ(L"Bounds",
3480 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3481 EXPECT_EQ((6u + 1u) * 2u, out_len);
3482
3483 // Show the negative cases of FPDFPageObjMark_GetName.
3484 out_len = 999u;
3485 EXPECT_FALSE(
3486 FPDFPageObjMark_GetName(nullptr, buffer, sizeof(buffer), &out_len));
3487 EXPECT_EQ(999u, out_len);
3488
3489 EXPECT_FALSE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), nullptr));
3490
3491 UnloadPage(page);
3492}
3493
Lei Zhangab41f252018-12-23 03:10:50 +00003494TEST_F(FPDFEditEmbedderTest, MarkGetParamKey) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003495 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003496 FPDF_PAGE page = LoadPage(0);
3497 ASSERT_TRUE(page);
3498 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
3499 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
3500 ASSERT_TRUE(mark);
3501
3502 char buffer[256];
3503 unsigned long out_len;
3504
3505 // Show the positive cases of FPDFPageObjMark_GetParamKey.
3506 out_len = 999u;
3507 EXPECT_TRUE(FPDFPageObjMark_GetParamKey(mark, 0, nullptr, 0, &out_len));
3508 EXPECT_EQ((8u + 1u) * 2u, out_len);
3509
3510 out_len = 999u;
3511 EXPECT_TRUE(
3512 FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer), &out_len));
3513 EXPECT_EQ(L"Position",
3514 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3515 EXPECT_EQ((8u + 1u) * 2u, out_len);
3516
3517 // Show the negative cases of FPDFPageObjMark_GetParamKey.
3518 out_len = 999u;
3519 EXPECT_FALSE(FPDFPageObjMark_GetParamKey(nullptr, 0, buffer, sizeof(buffer),
3520 &out_len));
3521 EXPECT_EQ(999u, out_len);
3522
3523 out_len = 999u;
3524 EXPECT_FALSE(
3525 FPDFPageObjMark_GetParamKey(mark, 1, buffer, sizeof(buffer), &out_len));
3526 EXPECT_EQ(999u, out_len);
3527
3528 EXPECT_FALSE(
3529 FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer), nullptr));
3530
3531 UnloadPage(page);
3532}
3533
Lei Zhangab41f252018-12-23 03:10:50 +00003534TEST_F(FPDFEditEmbedderTest, MarkGetIntParam) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003535 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003536 FPDF_PAGE page = LoadPage(0);
3537 ASSERT_TRUE(page);
3538 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 8);
3539 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 0);
3540 ASSERT_TRUE(mark);
3541
3542 int out_value;
3543
3544 // Show the positive cases of FPDFPageObjMark_GetParamIntValue.
3545 out_value = 999;
3546 EXPECT_TRUE(FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
3547 EXPECT_EQ(3, out_value);
3548
3549 // Show the negative cases of FPDFPageObjMark_GetParamIntValue.
3550 out_value = 999;
3551 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(nullptr, "Factor", &out_value));
3552 EXPECT_EQ(999, out_value);
3553
3554 out_value = 999;
3555 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(mark, "ParamThatDoesNotExist",
3556 &out_value));
3557 EXPECT_EQ(999, out_value);
3558
3559 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(mark, "Factor", nullptr));
3560
3561 page_object = FPDFPage_GetObject(page, 18);
3562 mark = FPDFPageObj_GetMark(page_object, 1);
3563 out_value = 999;
3564 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(mark, "Position", &out_value));
3565 EXPECT_EQ(999, out_value);
3566
3567 UnloadPage(page);
3568}
3569
Lei Zhangab41f252018-12-23 03:10:50 +00003570TEST_F(FPDFEditEmbedderTest, MarkGetStringParam) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003571 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003572 FPDF_PAGE page = LoadPage(0);
3573 ASSERT_TRUE(page);
3574 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
3575 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
3576 ASSERT_TRUE(mark);
3577
3578 char buffer[256];
3579 unsigned long out_len;
3580
3581 // Show the positive cases of FPDFPageObjMark_GetParamStringValue.
3582 out_len = 999u;
3583 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(mark, "Position", nullptr, 0,
3584 &out_len));
3585 EXPECT_EQ((4u + 1u) * 2u, out_len);
3586
3587 out_len = 999u;
3588 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(mark, "Position", buffer,
3589 sizeof(buffer), &out_len));
3590 EXPECT_EQ(L"Last",
3591 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3592 EXPECT_EQ((4u + 1u) * 2u, out_len);
3593
3594 // Show the negative cases of FPDFPageObjMark_GetParamStringValue.
3595 out_len = 999u;
3596 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(nullptr, "Position", buffer,
3597 sizeof(buffer), &out_len));
3598 EXPECT_EQ(999u, out_len);
3599
3600 out_len = 999u;
3601 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(
3602 mark, "ParamThatDoesNotExist", buffer, sizeof(buffer), &out_len));
3603 EXPECT_EQ(999u, out_len);
3604
3605 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(mark, "Position", buffer,
3606 sizeof(buffer), nullptr));
3607
3608 page_object = FPDFPage_GetObject(page, 8);
3609 mark = FPDFPageObj_GetMark(page_object, 0);
3610 out_len = 999u;
3611 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(mark, "Factor", buffer,
3612 sizeof(buffer), &out_len));
3613 EXPECT_EQ(999u, out_len);
3614
3615 UnloadPage(page);
3616}
3617
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003618TEST_F(FPDFEditEmbedderTest, GetBitmap) {
Jane Liu28fb7ba2017-08-02 21:45:57 -04003619 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3620 FPDF_PAGE page = LoadPage(0);
3621 ASSERT_TRUE(page);
Miklos Vajna92627612017-09-25 12:59:29 +02003622 ASSERT_EQ(39, FPDFPage_CountObjects(page));
Jane Liu28fb7ba2017-08-02 21:45:57 -04003623
3624 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 32);
3625 EXPECT_NE(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3626 EXPECT_FALSE(FPDFImageObj_GetBitmap(obj));
3627
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003628 {
3629 obj = FPDFPage_GetObject(page, 33);
3630 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3631 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3632 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
Lei Zhang85166512020-07-14 23:28:56 +00003633 CompareBitmap(bitmap.get(), 109, 88, kEmbeddedImage33Checksum);
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003634 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003635
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003636 {
3637 obj = FPDFPage_GetObject(page, 34);
3638 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3639 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3640 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3641 CompareBitmap(bitmap.get(), 103, 75, "c8d51fa6821ceb2a67f08446ff236c40");
3642 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003643
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003644 {
3645 obj = FPDFPage_GetObject(page, 35);
3646 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3647 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3648 EXPECT_EQ(FPDFBitmap_Gray, FPDFBitmap_GetFormat(bitmap.get()));
3649 CompareBitmap(bitmap.get(), 92, 68, "9c6d76cb1e37ef8514f9455d759391f3");
3650 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003651
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003652 {
3653 obj = FPDFPage_GetObject(page, 36);
3654 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3655 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3656 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3657 CompareBitmap(bitmap.get(), 79, 60, "f4e72fb783a01c7b4614cdc25eaa98ac");
3658 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003659
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003660 {
3661 obj = FPDFPage_GetObject(page, 37);
3662 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3663 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3664 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3665 CompareBitmap(bitmap.get(), 126, 106, "2cf9e66414c72461f4ccbf9cdebdfa1b");
3666 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003667
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003668 {
3669 obj = FPDFPage_GetObject(page, 38);
3670 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3671 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3672 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3673 CompareBitmap(bitmap.get(), 194, 119, "a8f3a126cec274dab8242fd2ccdc1b8b");
3674 }
3675
Jane Liu28fb7ba2017-08-02 21:45:57 -04003676 UnloadPage(page);
3677}
Jane Liu548334e2017-08-03 16:33:40 -04003678
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003679TEST_F(FPDFEditEmbedderTest, GetBitmapIgnoresSetMatrix) {
Lei Zhang85166512020-07-14 23:28:56 +00003680 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3681 FPDF_PAGE page = LoadPage(0);
3682 ASSERT_TRUE(page);
3683 ASSERT_EQ(39, FPDFPage_CountObjects(page));
3684
3685 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3686 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3687
3688 {
3689 // Render |obj| as is.
3690 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3691 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3692 CompareBitmap(bitmap.get(), 109, 88, kEmbeddedImage33Checksum);
3693 }
3694
3695 // Check the matrix for |obj|.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003696 FS_MATRIX matrix;
3697 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3698 EXPECT_FLOAT_EQ(53.0f, matrix.a);
3699 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3700 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3701 EXPECT_FLOAT_EQ(43.0f, matrix.d);
3702 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3703 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang85166512020-07-14 23:28:56 +00003704
3705 // Modify the matrix for |obj|.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003706 matrix.a = 120.0;
3707 EXPECT_TRUE(FPDFPageObj_SetMatrix(obj, &matrix));
Lei Zhang85166512020-07-14 23:28:56 +00003708
3709 // Make sure the matrix modification took place.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003710 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3711 EXPECT_FLOAT_EQ(120.0f, matrix.a);
3712 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3713 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3714 EXPECT_FLOAT_EQ(43.0f, matrix.d);
3715 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3716 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang85166512020-07-14 23:28:56 +00003717
3718 {
Lei Zhangc8601bf2021-06-29 23:19:27 +00003719 // Render |obj| again. Note that the FPDFPageObj_SetMatrix() call has no
Lei Zhang85166512020-07-14 23:28:56 +00003720 // effect.
3721 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3722 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3723 CompareBitmap(bitmap.get(), 109, 88, kEmbeddedImage33Checksum);
3724 }
3725
3726 UnloadPage(page);
3727}
3728
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003729TEST_F(FPDFEditEmbedderTest, GetBitmapForJBigImage) {
Lei Zhang53341dd2018-03-01 15:42:47 +00003730 ASSERT_TRUE(OpenDocument("bug_631912.pdf"));
3731 FPDF_PAGE page = LoadPage(0);
3732 ASSERT_TRUE(page);
3733 ASSERT_EQ(1, FPDFPage_CountObjects(page));
3734
3735 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
3736 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3737 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00003738 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
Lei Zhang1330ebb2018-03-05 15:16:37 +00003739 ASSERT_TRUE(bitmap);
3740 EXPECT_EQ(FPDFBitmap_Gray, FPDFBitmap_GetFormat(bitmap.get()));
3741 CompareBitmap(bitmap.get(), 1152, 720, "3f6a48e2b3e91b799bf34567f55cb4de");
Lei Zhang53341dd2018-03-01 15:42:47 +00003742 }
3743
3744 UnloadPage(page);
3745}
3746
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003747TEST_F(FPDFEditEmbedderTest, GetBitmapIgnoresSMask) {
Lei Zhang2e1b4f22020-07-08 23:40:18 +00003748 ASSERT_TRUE(OpenDocument("matte.pdf"));
3749 FPDF_PAGE page = LoadPage(0);
3750 ASSERT_TRUE(page);
3751
3752 constexpr int kExpectedObjects = 4;
3753 ASSERT_EQ(kExpectedObjects, FPDFPage_CountObjects(page));
3754
3755 for (int i = 0; i < kExpectedObjects; ++i) {
3756 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, i);
3757 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3758 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3759 ASSERT_TRUE(bitmap);
3760 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3761 CompareBitmap(bitmap.get(), 50, 50, "46c9a1dbe0b44765ce46017ad629a2fe");
3762 }
3763
3764 UnloadPage(page);
3765}
3766
Hui Yingst822fb8d2020-10-05 22:10:35 +00003767// TODO(crbug.com/pdfium/11): Fix this test and enable.
3768#if defined(_SKIA_SUPPORT_)
3769#define MAYBE_GetRenderedBitmapHandlesSetMatrix \
3770 DISABLED_GetRenderedBitmapHandlesSetMatrix
3771#else
3772#define MAYBE_GetRenderedBitmapHandlesSetMatrix \
3773 GetRenderedBitmapHandlesSetMatrix
3774#endif
3775TEST_F(FPDFEditEmbedderTest, MAYBE_GetRenderedBitmapHandlesSetMatrix) {
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003776 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3777 FPDF_PAGE page = LoadPage(0);
3778 ASSERT_TRUE(page);
3779 ASSERT_EQ(39, FPDFPage_CountObjects(page));
3780
3781 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3782 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3783
3784 {
3785 // Render |obj| as is.
3786 ScopedFPDFBitmap bitmap(
3787 FPDFImageObj_GetRenderedBitmap(document(), page, obj));
3788 EXPECT_EQ(FPDFBitmap_BGRA, FPDFBitmap_GetFormat(bitmap.get()));
Tom Sepezd661dc72021-06-24 20:22:19 +00003789 CompareBitmap(bitmap.get(), 53, 43, "582ca300e003f512d7b552c7b5b45d2e");
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003790 }
3791
3792 // Check the matrix for |obj|.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003793 FS_MATRIX matrix;
3794 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3795 EXPECT_FLOAT_EQ(53.0f, matrix.a);
3796 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3797 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3798 EXPECT_FLOAT_EQ(43.0f, matrix.d);
3799 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3800 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003801
3802 // Modify the matrix for |obj|.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003803 matrix.a = 120.0;
3804 EXPECT_TRUE(FPDFPageObj_SetMatrix(obj, &matrix));
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003805
3806 // Make sure the matrix modification took place.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003807 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3808 EXPECT_FLOAT_EQ(120.0f, matrix.a);
3809 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3810 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3811 EXPECT_FLOAT_EQ(43.0f, matrix.d);
3812 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3813 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003814
3815 {
Lei Zhangc8601bf2021-06-29 23:19:27 +00003816 // Render |obj| again. Note that the FPDFPageObj_SetMatrix() call has an
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003817 // effect.
3818 ScopedFPDFBitmap bitmap(
3819 FPDFImageObj_GetRenderedBitmap(document(), page, obj));
3820 EXPECT_EQ(FPDFBitmap_BGRA, FPDFBitmap_GetFormat(bitmap.get()));
Tom Sepezd661dc72021-06-24 20:22:19 +00003821 CompareBitmap(bitmap.get(), 120, 43, "0824c16dcf2dfcef44b45d88db1fddce");
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003822 }
3823
3824 UnloadPage(page);
3825}
3826
Hui Yingst822fb8d2020-10-05 22:10:35 +00003827// TODO(crbug.com/pdfium/11): Fix this test and enable.
3828#if defined(_SKIA_SUPPORT_)
3829#define MAYBE_GetRenderedBitmapHandlesSMask \
3830 DISABLED_GetRenderedBitmapHandlesSMask
3831#else
3832#define MAYBE_GetRenderedBitmapHandlesSMask GetRenderedBitmapHandlesSMask
3833#endif
3834TEST_F(FPDFEditEmbedderTest, MAYBE_GetRenderedBitmapHandlesSMask) {
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003835 ASSERT_TRUE(OpenDocument("matte.pdf"));
3836 FPDF_PAGE page = LoadPage(0);
3837 ASSERT_TRUE(page);
3838
3839 constexpr int kExpectedObjects = 4;
3840 ASSERT_EQ(kExpectedObjects, FPDFPage_CountObjects(page));
3841
3842 for (int i = 0; i < kExpectedObjects; ++i) {
3843 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, i);
3844 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3845 ScopedFPDFBitmap bitmap(
3846 FPDFImageObj_GetRenderedBitmap(document(), page, obj));
3847 ASSERT_TRUE(bitmap);
3848 EXPECT_EQ(FPDFBitmap_BGRA, FPDFBitmap_GetFormat(bitmap.get()));
3849 if (i == 0)
3850 CompareBitmap(bitmap.get(), 40, 60, "5a3ae4a660ce919e29c42ec2258142f1");
3851 else
3852 CompareBitmap(bitmap.get(), 40, 60, "67504e83f5d78214ea00efc19082c5c1");
3853 }
3854
3855 UnloadPage(page);
3856}
3857
3858TEST_F(FPDFEditEmbedderTest, GetRenderedBitmapBadParams) {
3859 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3860 FPDF_PAGE page = LoadPage(0);
3861 ASSERT_TRUE(page);
3862
3863 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3864 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3865
3866 // Test various null parameters.
3867 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, nullptr, nullptr));
3868 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(document(), nullptr, nullptr));
3869 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, page, nullptr));
3870 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, nullptr, obj));
3871 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(document(), page, nullptr));
3872 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, page, obj));
3873
3874 // Test mismatch between document and page parameters.
3875 ScopedFPDFDocument new_document(FPDF_CreateNewDocument());
3876 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(new_document.get(), page, obj));
3877
3878 UnloadPage(page);
3879}
3880
Lei Zhangab41f252018-12-23 03:10:50 +00003881TEST_F(FPDFEditEmbedderTest, GetImageData) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003882 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
Jane Liu548334e2017-08-03 16:33:40 -04003883 FPDF_PAGE page = LoadPage(0);
3884 ASSERT_TRUE(page);
Miklos Vajna92627612017-09-25 12:59:29 +02003885 ASSERT_EQ(39, FPDFPage_CountObjects(page));
Jane Liu548334e2017-08-03 16:33:40 -04003886
3887 // Retrieve an image object with flate-encoded data stream.
3888 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3889 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3890
3891 // Check that the raw image data has the correct length and hash value.
3892 unsigned long len = FPDFImageObj_GetImageDataRaw(obj, nullptr, 0);
3893 std::vector<char> buf(len);
3894 EXPECT_EQ(4091u, FPDFImageObj_GetImageDataRaw(obj, buf.data(), len));
3895 EXPECT_EQ("f73802327d2e88e890f653961bcda81a",
3896 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3897
3898 // Check that the decoded image data has the correct length and hash value.
3899 len = FPDFImageObj_GetImageDataDecoded(obj, nullptr, 0);
3900 buf.clear();
3901 buf.resize(len);
3902 EXPECT_EQ(28776u, FPDFImageObj_GetImageDataDecoded(obj, buf.data(), len));
Lei Zhang85166512020-07-14 23:28:56 +00003903 EXPECT_EQ(kEmbeddedImage33Checksum,
Jane Liu548334e2017-08-03 16:33:40 -04003904 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3905
Lei Zhang351e8b02018-12-20 01:10:06 +00003906 // Retrieve an image object with DCTDecode-encoded data stream.
Jane Liu548334e2017-08-03 16:33:40 -04003907 obj = FPDFPage_GetObject(page, 37);
3908 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3909
3910 // Check that the raw image data has the correct length and hash value.
3911 len = FPDFImageObj_GetImageDataRaw(obj, nullptr, 0);
3912 buf.clear();
3913 buf.resize(len);
3914 EXPECT_EQ(4370u, FPDFImageObj_GetImageDataRaw(obj, buf.data(), len));
3915 EXPECT_EQ("6aae1f3710335023a9e12191be66b64b",
3916 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3917
3918 // Check that the decoded image data has the correct length and hash value,
3919 // which should be the same as those of the raw data, since this image is
3920 // encoded by a single DCTDecode filter and decoding is a noop.
3921 len = FPDFImageObj_GetImageDataDecoded(obj, nullptr, 0);
3922 buf.clear();
3923 buf.resize(len);
3924 EXPECT_EQ(4370u, FPDFImageObj_GetImageDataDecoded(obj, buf.data(), len));
3925 EXPECT_EQ("6aae1f3710335023a9e12191be66b64b",
3926 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3927
3928 UnloadPage(page);
3929}
Jane Liu2e5f0ae2017-08-08 15:23:27 -04003930
Lei Zhangab41f252018-12-23 03:10:50 +00003931TEST_F(FPDFEditEmbedderTest, GetImageMatrix) {
Lei Zhang866d6882018-10-24 17:31:01 +00003932 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3933 FPDF_PAGE page = LoadPage(0);
3934 ASSERT_TRUE(page);
3935 ASSERT_EQ(39, FPDFPage_CountObjects(page));
3936
3937 FPDF_PAGEOBJECT obj;
Lei Zhangc8601bf2021-06-29 23:19:27 +00003938 FS_MATRIX matrix;
Lei Zhang866d6882018-10-24 17:31:01 +00003939
3940 obj = FPDFPage_GetObject(page, 33);
3941 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003942 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3943 EXPECT_FLOAT_EQ(53.0f, matrix.a);
3944 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3945 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3946 EXPECT_FLOAT_EQ(43.0f, matrix.d);
3947 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3948 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003949
3950 obj = FPDFPage_GetObject(page, 34);
3951 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003952 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3953 EXPECT_FLOAT_EQ(70.0f, matrix.a);
3954 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3955 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3956 EXPECT_FLOAT_EQ(51.0f, matrix.d);
3957 EXPECT_FLOAT_EQ(216.0f, matrix.e);
3958 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003959
3960 obj = FPDFPage_GetObject(page, 35);
3961 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003962 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3963 EXPECT_FLOAT_EQ(69.0f, matrix.a);
3964 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3965 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3966 EXPECT_FLOAT_EQ(51.0f, matrix.d);
3967 EXPECT_FLOAT_EQ(360.0f, matrix.e);
3968 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003969
3970 obj = FPDFPage_GetObject(page, 36);
3971 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003972 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3973 EXPECT_FLOAT_EQ(59.0f, matrix.a);
3974 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3975 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3976 EXPECT_FLOAT_EQ(45.0f, matrix.d);
3977 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3978 EXPECT_FLOAT_EQ(553.510009765625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003979
3980 obj = FPDFPage_GetObject(page, 37);
3981 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003982 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3983 EXPECT_FLOAT_EQ(55.94000244140625f, matrix.a);
3984 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3985 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3986 EXPECT_FLOAT_EQ(46.950000762939453f, matrix.d);
3987 EXPECT_FLOAT_EQ(216.0f, matrix.e);
3988 EXPECT_FLOAT_EQ(552.510009765625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003989
3990 obj = FPDFPage_GetObject(page, 38);
3991 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003992 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3993 EXPECT_FLOAT_EQ(70.528999328613281f, matrix.a);
3994 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3995 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3996 EXPECT_FLOAT_EQ(43.149997711181641f, matrix.d);
3997 EXPECT_FLOAT_EQ(360.0f, matrix.e);
3998 EXPECT_FLOAT_EQ(553.3599853515625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003999
4000 UnloadPage(page);
4001}
4002
Lei Zhangab41f252018-12-23 03:10:50 +00004003TEST_F(FPDFEditEmbedderTest, DestroyPageObject) {
Jane Liu2e5f0ae2017-08-08 15:23:27 -04004004 FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
4005 ASSERT_TRUE(rect);
4006
4007 // There should be no memory leaks with a call to FPDFPageObj_Destroy().
4008 FPDFPageObj_Destroy(rect);
4009}
Jane Liube63ab92017-08-09 14:09:34 -04004010
Lei Zhangab41f252018-12-23 03:10:50 +00004011TEST_F(FPDFEditEmbedderTest, GetImageFilters) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00004012 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
Jane Liube63ab92017-08-09 14:09:34 -04004013 FPDF_PAGE page = LoadPage(0);
4014 ASSERT_TRUE(page);
4015
4016 // Verify that retrieving the filter of a non-image object would fail.
4017 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 32);
4018 ASSERT_NE(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
4019 ASSERT_EQ(0, FPDFImageObj_GetImageFilterCount(obj));
4020 EXPECT_EQ(0u, FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0));
4021
4022 // Verify the returned filter string for an image object with a single filter.
4023 obj = FPDFPage_GetObject(page, 33);
4024 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
4025 ASSERT_EQ(1, FPDFImageObj_GetImageFilterCount(obj));
4026 unsigned long len = FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0);
4027 std::vector<char> buf(len);
Lei Zhang0733a1b2017-08-31 12:36:31 -07004028 static constexpr char kFlateDecode[] = "FlateDecode";
4029 EXPECT_EQ(sizeof(kFlateDecode),
4030 FPDFImageObj_GetImageFilter(obj, 0, buf.data(), len));
4031 EXPECT_STREQ(kFlateDecode, buf.data());
Jane Liube63ab92017-08-09 14:09:34 -04004032 EXPECT_EQ(0u, FPDFImageObj_GetImageFilter(obj, 1, nullptr, 0));
4033
4034 // Verify all the filters for an image object with a list of filters.
4035 obj = FPDFPage_GetObject(page, 38);
4036 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
4037 ASSERT_EQ(2, FPDFImageObj_GetImageFilterCount(obj));
4038 len = FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0);
4039 buf.clear();
4040 buf.resize(len);
Lei Zhang0733a1b2017-08-31 12:36:31 -07004041 static constexpr char kASCIIHexDecode[] = "ASCIIHexDecode";
4042 EXPECT_EQ(sizeof(kASCIIHexDecode),
4043 FPDFImageObj_GetImageFilter(obj, 0, buf.data(), len));
4044 EXPECT_STREQ(kASCIIHexDecode, buf.data());
Jane Liube63ab92017-08-09 14:09:34 -04004045
4046 len = FPDFImageObj_GetImageFilter(obj, 1, nullptr, 0);
4047 buf.clear();
4048 buf.resize(len);
Lei Zhang0733a1b2017-08-31 12:36:31 -07004049 static constexpr char kDCTDecode[] = "DCTDecode";
4050 EXPECT_EQ(sizeof(kDCTDecode),
4051 FPDFImageObj_GetImageFilter(obj, 1, buf.data(), len));
4052 EXPECT_STREQ(kDCTDecode, buf.data());
Jane Liube63ab92017-08-09 14:09:34 -04004053
4054 UnloadPage(page);
4055}
Jane Liuca898292017-08-16 11:25:35 -04004056
Lei Zhangab41f252018-12-23 03:10:50 +00004057TEST_F(FPDFEditEmbedderTest, GetImageMetadata) {
Jane Liuca898292017-08-16 11:25:35 -04004058 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
4059 FPDF_PAGE page = LoadPage(0);
4060 ASSERT_TRUE(page);
4061
4062 // Check that getting the metadata of a null object would fail.
4063 FPDF_IMAGEOBJ_METADATA metadata;
4064 EXPECT_FALSE(FPDFImageObj_GetImageMetadata(nullptr, page, &metadata));
4065
4066 // Check that receiving the metadata with a null metadata object would fail.
4067 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 35);
4068 EXPECT_FALSE(FPDFImageObj_GetImageMetadata(obj, page, nullptr));
4069
4070 // Check that when retrieving an image object's metadata without passing in
4071 // |page|, all values are correct, with the last two being default values.
4072 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
4073 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, nullptr, &metadata));
Julian Lungerecd063e2017-12-27 10:18:50 -05004074 EXPECT_EQ(7, metadata.marked_content_id);
Jane Liuca898292017-08-16 11:25:35 -04004075 EXPECT_EQ(92u, metadata.width);
4076 EXPECT_EQ(68u, metadata.height);
Lei Zhang351e8b02018-12-20 01:10:06 +00004077 EXPECT_FLOAT_EQ(96.0f, metadata.horizontal_dpi);
4078 EXPECT_FLOAT_EQ(96.0f, metadata.vertical_dpi);
Jane Liuca898292017-08-16 11:25:35 -04004079 EXPECT_EQ(0u, metadata.bits_per_pixel);
4080 EXPECT_EQ(FPDF_COLORSPACE_UNKNOWN, metadata.colorspace);
4081
4082 // Verify the metadata of a bitmap image with indexed colorspace.
4083 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata));
Julian Lungerecd063e2017-12-27 10:18:50 -05004084 EXPECT_EQ(7, metadata.marked_content_id);
Jane Liuca898292017-08-16 11:25:35 -04004085 EXPECT_EQ(92u, metadata.width);
4086 EXPECT_EQ(68u, metadata.height);
Lei Zhang351e8b02018-12-20 01:10:06 +00004087 EXPECT_FLOAT_EQ(96.0f, metadata.horizontal_dpi);
4088 EXPECT_FLOAT_EQ(96.0f, metadata.vertical_dpi);
Jane Liuca898292017-08-16 11:25:35 -04004089 EXPECT_EQ(1u, metadata.bits_per_pixel);
4090 EXPECT_EQ(FPDF_COLORSPACE_INDEXED, metadata.colorspace);
4091
4092 // Verify the metadata of an image with RGB colorspace.
4093 obj = FPDFPage_GetObject(page, 37);
4094 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
4095 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata));
Julian Lungerecd063e2017-12-27 10:18:50 -05004096 EXPECT_EQ(9, metadata.marked_content_id);
Jane Liuca898292017-08-16 11:25:35 -04004097 EXPECT_EQ(126u, metadata.width);
4098 EXPECT_EQ(106u, metadata.height);
Lei Zhang351e8b02018-12-20 01:10:06 +00004099 EXPECT_FLOAT_EQ(162.173752f, metadata.horizontal_dpi);
4100 EXPECT_FLOAT_EQ(162.555878f, metadata.vertical_dpi);
Jane Liuca898292017-08-16 11:25:35 -04004101 EXPECT_EQ(24u, metadata.bits_per_pixel);
4102 EXPECT_EQ(FPDF_COLORSPACE_DEVICERGB, metadata.colorspace);
4103
4104 UnloadPage(page);
4105}
Lei Zhangdc1b7392020-05-14 21:15:53 +00004106
4107TEST_F(FPDFEditEmbedderTest, GetImageMetadataJpxLzw) {
4108 ASSERT_TRUE(OpenDocument("jpx_lzw.pdf"));
4109 FPDF_PAGE page = LoadPage(0);
4110 ASSERT_TRUE(page);
4111
4112 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
4113 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
4114
4115 FPDF_IMAGEOBJ_METADATA metadata;
4116 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata));
4117 EXPECT_EQ(-1, metadata.marked_content_id);
4118 EXPECT_EQ(612u, metadata.width);
4119 EXPECT_EQ(792u, metadata.height);
4120 EXPECT_FLOAT_EQ(72.0f, metadata.horizontal_dpi);
4121 EXPECT_FLOAT_EQ(72.0f, metadata.vertical_dpi);
4122 EXPECT_EQ(24u, metadata.bits_per_pixel);
4123 EXPECT_EQ(FPDF_COLORSPACE_UNKNOWN, metadata.colorspace);
4124
4125 UnloadPage(page);
4126}