blob: f16f5d55ac9a65b69960db8bf883181330b99e5a [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"
Nicolas Pena0fc185e2017-02-08 12:13:20 -050019#include "core/fxcrt/fx_system.h"
Lei Zhang0dcb8fd2019-02-07 00:46:04 +000020#include "core/fxge/fx_font.h"
Dan Sinclair00d47a62018-03-28 18:39:04 +000021#include "fpdfsdk/cpdfsdk_helpers.h"
Tom Sepeze08d2b12018-04-25 18:49:32 +000022#include "public/cpp/fpdf_scopers.h"
Jane Liueda65252017-06-07 11:31:27 -040023#include "public/fpdf_annot.h"
Tom Sepezd483eb42016-01-06 10:03:59 -080024#include "public/fpdf_edit.h"
25#include "public/fpdfview.h"
26#include "testing/embedder_test.h"
Hui Yingstb4baceb2020-04-28 23:46:10 +000027#include "testing/embedder_test_constants.h"
Lei Zhangb6992dd2019-02-05 23:30:20 +000028#include "testing/fx_string_testhelpers.h"
Tom Sepez0aec19b2016-01-07 12:22:44 -080029#include "testing/gmock/include/gmock/gmock-matchers.h"
Tom Sepezd483eb42016-01-06 10:03:59 -080030#include "testing/gtest/include/gtest/gtest.h"
Hui Yingst8e88e382020-11-02 18:19:56 +000031#include "testing/utils/file_util.h"
Lei Zhang4c64e962019-02-05 19:24:12 +000032#include "testing/utils/hash.h"
Hui Yingst8e88e382020-11-02 18:19:56 +000033#include "testing/utils/path_service.h"
Tom Sepez9c78c0d2021-01-27 20:13:14 +000034#include "third_party/base/check.h"
Tom Sepezd483eb42016-01-06 10:03:59 -080035
Hui Yingstb4baceb2020-04-28 23:46:10 +000036using pdfium::kHelloWorldChecksum;
37
38namespace {
39
Hui Yingst3b6136a2020-06-09 00:39:33 +000040const char kAllRemovedChecksum[] = "eee4600ac08b458ac7ac2320e225674c";
41
42const wchar_t kBottomText[] = L"I'm at the bottom of the page";
43
Hui Yingst5ce6a3f2020-11-11 02:29:09 +000044#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
45static constexpr char kBottomTextChecksum[] =
46 "5df7be86df1e18819723cdd9c81c2c7d";
Hui Yingst3b6136a2020-06-09 00:39:33 +000047#else
Hui Yingst5ce6a3f2020-11-11 02:29:09 +000048#if defined(OS_WIN)
49static constexpr char kBottomTextChecksum[] =
50 "08d1ff3e5a42801bee6077fd366bef00";
51#elif defined(OS_APPLE)
52static constexpr char kBottomTextChecksum[] =
53 "324e1db8164a040cf6104538baa95ba6";
54#else
55static constexpr char kBottomTextChecksum[] =
56 "eacaa24573b8ce997b3882595f096f00";
Hui Yingst3b6136a2020-06-09 00:39:33 +000057#endif
Hui Yingst5ce6a3f2020-11-11 02:29:09 +000058#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingstb4baceb2020-04-28 23:46:10 +000059
Hui Yingst08c40712020-04-29 01:37:35 +000060#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
61#if defined(OS_WIN)
62const char kFirstRemovedChecksum[] = "d468228cc55071a9e838f66afc0f58ff";
63#else
64const char kFirstRemovedChecksum[] = "0c79dc1065b1d06991e3ac4aaa35d25c";
65#endif // defined(OS_WIN)
66#else
Hui Yingstb4baceb2020-04-28 23:46:10 +000067#if defined(OS_WIN)
68const char kFirstRemovedChecksum[] = "aae6c5334721f90ec30d3d59f4ef7deb";
Lei Zhang0c03d632020-07-30 17:05:36 +000069#elif defined(OS_APPLE)
Hui Yingstb4baceb2020-04-28 23:46:10 +000070const char kFirstRemovedChecksum[] = "17ca3778fd8bb395b46532f1fa17f702";
71#else
72const char kFirstRemovedChecksum[] = "b76df015fe88009c3c342395df96abf1";
73#endif
Hui Yingst08c40712020-04-29 01:37:35 +000074#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingstb4baceb2020-04-28 23:46:10 +000075
Hui Yingst3b6136a2020-06-09 00:39:33 +000076const wchar_t kLoadedFontText[] = L"I am testing my loaded font, WEE.";
77
Hui Yingst9d6ec8f2020-11-05 23:35:38 +000078#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
79const char kLoadedFontTextChecksum[] = "a1dffe52c1b9ded5fe8d77eb10d8cc19";
80#else
Hui Yingst3b6136a2020-06-09 00:39:33 +000081#if defined(OS_WIN)
82const char kLoadedFontTextChecksum[] = "d60ba39f9698e32360d99e727dd93165";
Lei Zhang0c03d632020-07-30 17:05:36 +000083#elif defined(OS_APPLE)
Hui Yingst3b6136a2020-06-09 00:39:33 +000084const char kLoadedFontTextChecksum[] = "fc921c0bbdde73986ac13c15a85db4c3";
85#else
86const char kLoadedFontTextChecksum[] = "70592859010ffbf532a2237b8118bcc4";
87#endif
Hui Yingst9d6ec8f2020-11-05 23:35:38 +000088#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingst3b6136a2020-06-09 00:39:33 +000089
90const char kRedRectangleChecksum[] = "66d02eaa6181e2c069ce2ea99beda497";
91
Lei Zhang85166512020-07-14 23:28:56 +000092// In embedded_images.pdf.
93const char kEmbeddedImage33Checksum[] = "cb3637934bb3b95a6e4ae1ea9eb9e56e";
94
Hui Yingstb4baceb2020-04-28 23:46:10 +000095} // namespace
96
Lei Zhangab41f252018-12-23 03:10:50 +000097class FPDFEditEmbedderTest : public EmbedderTest {
Nicolas Penad03ca422017-03-06 13:54:33 -050098 protected:
99 FPDF_DOCUMENT CreateNewDocument() {
100 document_ = FPDF_CreateNewDocument();
Tom Sepez41066c12017-05-18 09:28:49 -0700101 cpdf_doc_ = CPDFDocumentFromFPDFDocument(document_);
Nicolas Penad03ca422017-03-06 13:54:33 -0500102 return document_;
103 }
104
Lei Zhang710fa992018-05-25 16:24:48 +0000105 void CheckFontDescriptor(const CPDF_Dictionary* font_dict,
Nicolas Penad03ca422017-03-06 13:54:33 -0500106 int font_type,
107 bool bold,
108 bool italic,
Tom Sepez20c41a52018-08-29 23:53:53 +0000109 pdfium::span<const uint8_t> span) {
Lei Zhangb1ec2802018-05-25 21:55:24 +0000110 const CPDF_Dictionary* font_desc = font_dict->GetDictFor("FontDescriptor");
Nicolas Penad03ca422017-03-06 13:54:33 -0500111 ASSERT_TRUE(font_desc);
Lei Zhanga228ff32020-06-24 17:39:33 +0000112 EXPECT_EQ("FontDescriptor", font_desc->GetNameFor("Type"));
113 ByteString font_name = font_desc->GetNameFor("FontName");
114 EXPECT_FALSE(font_name.IsEmpty());
115 EXPECT_EQ(font_dict->GetNameFor("BaseFont"), font_name);
Nicolas Penad03ca422017-03-06 13:54:33 -0500116
117 // Check that the font descriptor has the required keys according to spec
118 // 1.7 Table 5.19
119 ASSERT_TRUE(font_desc->KeyExist("Flags"));
Dan Sinclair10e1f052017-09-28 15:59:42 -0400120
Nicolas Penad03ca422017-03-06 13:54:33 -0500121 int font_flags = font_desc->GetIntegerFor("Flags");
Lei Zhang44d03832019-10-18 18:45:31 +0000122 EXPECT_EQ(bold, FontStyleIsForceBold(font_flags));
Dan Sinclair10e1f052017-09-28 15:59:42 -0400123 EXPECT_EQ(italic, FontStyleIsItalic(font_flags));
124 EXPECT_TRUE(FontStyleIsNonSymbolic(font_flags));
Nicolas Penad03ca422017-03-06 13:54:33 -0500125 ASSERT_TRUE(font_desc->KeyExist("FontBBox"));
Nicolás Peña5f95f362017-09-28 13:00:45 +0900126
Lei Zhangb1ec2802018-05-25 21:55:24 +0000127 const CPDF_Array* fontBBox = font_desc->GetArrayFor("FontBBox");
Nicolás Peña5f95f362017-09-28 13:00:45 +0900128 ASSERT_TRUE(fontBBox);
Lei Zhangf40380f2018-10-12 18:31:51 +0000129 EXPECT_EQ(4u, fontBBox->size());
Nicolás Peña5f95f362017-09-28 13:00:45 +0900130 // Check that the coordinates are in the preferred order according to spec
131 // 1.7 Section 3.8.4
132 EXPECT_TRUE(fontBBox->GetIntegerAt(0) < fontBBox->GetIntegerAt(2));
133 EXPECT_TRUE(fontBBox->GetIntegerAt(1) < fontBBox->GetIntegerAt(3));
134
Nicolas Penad03ca422017-03-06 13:54:33 -0500135 EXPECT_TRUE(font_desc->KeyExist("ItalicAngle"));
136 EXPECT_TRUE(font_desc->KeyExist("Ascent"));
137 EXPECT_TRUE(font_desc->KeyExist("Descent"));
138 EXPECT_TRUE(font_desc->KeyExist("CapHeight"));
139 EXPECT_TRUE(font_desc->KeyExist("StemV"));
Ryan Harrison275e2602017-09-18 14:23:18 -0400140 ByteString present("FontFile");
141 ByteString absent("FontFile2");
Nicolas Penad03ca422017-03-06 13:54:33 -0500142 if (font_type == FPDF_FONT_TRUETYPE)
143 std::swap(present, absent);
144 EXPECT_TRUE(font_desc->KeyExist(present));
145 EXPECT_FALSE(font_desc->KeyExist(absent));
146
Artem Strygineababa12018-06-06 12:31:18 +0000147 auto streamAcc =
148 pdfium::MakeRetain<CPDF_StreamAcc>(font_desc->GetStreamFor(present));
149 streamAcc->LoadAllDataRaw();
150
Nicolas Penad03ca422017-03-06 13:54:33 -0500151 // Check that the font stream is the one that was provided
Tom Sepez20c41a52018-08-29 23:53:53 +0000152 ASSERT_EQ(span.size(), streamAcc->GetSize());
Nicolás Peña79eab232017-09-28 13:29:05 +0900153 if (font_type == FPDF_FONT_TRUETYPE) {
Tom Sepez20c41a52018-08-29 23:53:53 +0000154 ASSERT_EQ(static_cast<int>(span.size()),
Artem Strygineababa12018-06-06 12:31:18 +0000155 streamAcc->GetDict()->GetIntegerFor("Length1"));
Nicolás Peña79eab232017-09-28 13:29:05 +0900156 }
Artem Strygineababa12018-06-06 12:31:18 +0000157
158 const uint8_t* stream_data = streamAcc->GetData();
Tom Sepez20c41a52018-08-29 23:53:53 +0000159 for (size_t j = 0; j < span.size(); j++)
160 EXPECT_EQ(span[j], stream_data[j]) << " at byte " << j;
Nicolas Penad03ca422017-03-06 13:54:33 -0500161 }
162
Lei Zhangde579ab2018-05-25 21:49:49 +0000163 void CheckCompositeFontWidths(const CPDF_Array* widths_array,
Nicolas Penad03ca422017-03-06 13:54:33 -0500164 CPDF_Font* typed_font) {
165 // Check that W array is in a format that conforms to PDF spec 1.7 section
166 // "Glyph Metrics in CIDFonts" (these checks are not
167 // implementation-specific).
Lei Zhangf40380f2018-10-12 18:31:51 +0000168 EXPECT_GT(widths_array->size(), 1u);
Nicolas Penad03ca422017-03-06 13:54:33 -0500169 int num_cids_checked = 0;
170 int cur_cid = 0;
Lei Zhangf40380f2018-10-12 18:31:51 +0000171 for (size_t idx = 0; idx < widths_array->size(); idx++) {
Nicolas Penad03ca422017-03-06 13:54:33 -0500172 int cid = widths_array->GetNumberAt(idx);
173 EXPECT_GE(cid, cur_cid);
Lei Zhangf40380f2018-10-12 18:31:51 +0000174 ASSERT_FALSE(++idx == widths_array->size());
Lei Zhangde579ab2018-05-25 21:49:49 +0000175 const CPDF_Object* next = widths_array->GetObjectAt(idx);
Nicolas Penad03ca422017-03-06 13:54:33 -0500176 if (next->IsArray()) {
177 // We are in the c [w1 w2 ...] case
Lei Zhangde579ab2018-05-25 21:49:49 +0000178 const CPDF_Array* arr = next->AsArray();
Lei Zhangf40380f2018-10-12 18:31:51 +0000179 int cnt = static_cast<int>(arr->size());
Nicolas Penad03ca422017-03-06 13:54:33 -0500180 size_t inner_idx = 0;
181 for (cur_cid = cid; cur_cid < cid + cnt; cur_cid++) {
Lei Zhang70e66192020-09-18 20:50:51 +0000182 int width = arr->GetNumberAt(inner_idx++);
Dan Sinclair971a6742018-03-28 19:23:25 +0000183 EXPECT_EQ(width, typed_font->GetCharWidthF(cur_cid))
184 << " at cid " << cur_cid;
Nicolas Penad03ca422017-03-06 13:54:33 -0500185 }
186 num_cids_checked += cnt;
187 continue;
188 }
189 // Otherwise, are in the c_first c_last w case.
190 ASSERT_TRUE(next->IsNumber());
191 int last_cid = next->AsNumber()->GetInteger();
Lei Zhangf40380f2018-10-12 18:31:51 +0000192 ASSERT_FALSE(++idx == widths_array->size());
Lei Zhang70e66192020-09-18 20:50:51 +0000193 int width = widths_array->GetNumberAt(idx);
Nicolas Penad03ca422017-03-06 13:54:33 -0500194 for (cur_cid = cid; cur_cid <= last_cid; cur_cid++) {
Dan Sinclair971a6742018-03-28 19:23:25 +0000195 EXPECT_EQ(width, typed_font->GetCharWidthF(cur_cid))
196 << " at cid " << cur_cid;
Nicolas Penad03ca422017-03-06 13:54:33 -0500197 }
198 num_cids_checked += last_cid - cid + 1;
199 }
200 // Make sure we have a good amount of cids described
201 EXPECT_GT(num_cids_checked, 900);
202 }
203 CPDF_Document* cpdf_doc() { return cpdf_doc_; }
204
205 private:
206 CPDF_Document* cpdf_doc_;
207};
Tom Sepezd483eb42016-01-06 10:03:59 -0800208
etienneb7712c262016-04-26 08:13:45 -0700209namespace {
thestigdc7ec032016-11-21 15:32:52 -0800210
etienneb7712c262016-04-26 08:13:45 -0700211const char kExpectedPDF[] =
212 "%PDF-1.7\r\n"
213 "%\xA1\xB3\xC5\xD7\r\n"
214 "1 0 obj\r\n"
215 "<</Pages 2 0 R /Type/Catalog>>\r\n"
216 "endobj\r\n"
217 "2 0 obj\r\n"
218 "<</Count 1/Kids\\[ 4 0 R \\]/Type/Pages>>\r\n"
219 "endobj\r\n"
220 "3 0 obj\r\n"
221 "<</CreationDate\\(D:.*\\)/Creator\\(PDFium\\)>>\r\n"
222 "endobj\r\n"
223 "4 0 obj\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400224 "<</MediaBox\\[ 0 0 640 480\\]/Parent 2 0 R "
225 "/Resources<</ExtGState<</FXE1 5 0 R >>>>"
Nicolas Penad9d6c292017-06-06 16:12:10 -0400226 "/Rotate 0/Type/Page"
etienneb7712c262016-04-26 08:13:45 -0700227 ">>\r\n"
228 "endobj\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400229 "5 0 obj\r\n"
230 "<</BM/Normal/CA 1/ca 1>>\r\n"
231 "endobj\r\n"
etienneb7712c262016-04-26 08:13:45 -0700232 "xref\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400233 "0 6\r\n"
etienneb7712c262016-04-26 08:13:45 -0700234 "0000000000 65535 f\r\n"
235 "0000000017 00000 n\r\n"
236 "0000000066 00000 n\r\n"
237 "0000000122 00000 n\r\n"
238 "0000000192 00000 n\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400239 "0000000311 00000 n\r\n"
etienneb7712c262016-04-26 08:13:45 -0700240 "trailer\r\n"
241 "<<\r\n"
242 "/Root 1 0 R\r\n"
243 "/Info 3 0 R\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400244 "/Size 6/ID\\[<.*><.*>\\]>>\r\n"
etienneb7712c262016-04-26 08:13:45 -0700245 "startxref\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400246 "354\r\n"
etienneb7712c262016-04-26 08:13:45 -0700247 "%%EOF\r\n";
thestigdc7ec032016-11-21 15:32:52 -0800248
etienneb7712c262016-04-26 08:13:45 -0700249} // namespace
250
Hui Yingst8e88e382020-11-02 18:19:56 +0000251TEST_F(FPDFEditEmbedderTest, EmbedNotoSansSCFont) {
252 EXPECT_TRUE(CreateEmptyDocument());
253 ScopedFPDFPage page(FPDFPage_New(document(), 0, 400, 400));
254 std::string font_path;
Hui Yingst8532ef02020-11-04 19:17:17 +0000255 ASSERT_TRUE(PathService::GetThirdPartyFilePath(
256 "NotoSansCJK/NotoSansSC-Regular.subset.otf", &font_path));
Hui Yingst8e88e382020-11-02 18:19:56 +0000257
258 size_t file_length = 0;
259 std::unique_ptr<char, pdfium::FreeDeleter> font_data =
260 GetFileContents(font_path.c_str(), &file_length);
Tom Sepez9c78c0d2021-01-27 20:13:14 +0000261 DCHECK(font_data);
Hui Yingst8e88e382020-11-02 18:19:56 +0000262
263 ScopedFPDFFont font(FPDFText_LoadFont(
264 document(), reinterpret_cast<const uint8_t*>(font_data.get()),
265 file_length, FPDF_FONT_TRUETYPE, /*cid=*/true));
266 FPDF_PAGEOBJECT text_object =
267 FPDFPageObj_CreateTextObj(document(), font.get(), 20.0f);
268 EXPECT_TRUE(text_object);
269
270 // Test the characters which are either mapped to one single unicode or
271 // multiple unicodes in the embedded font.
272 ScopedFPDFWideString text = GetFPDFWideString(L"这是第一句。 这是第二行。");
273 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
274
275 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 50, 200);
276 FPDFPage_InsertObject(page.get(), text_object);
277 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
278
279#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
280#if defined(OS_APPLE)
281 const char kChecksum[] = "9a31fb87d1c6d2346bba22d1196041cd";
282#else
283 const char kChecksum[] = "5bb65e15fc0a685934cd5006dec08a76";
284#endif // defined(OS_APPLE)
285#else
286#if defined(OS_WIN)
287 const char kChecksum[] = "89e8eef5d6ad18c542a92a0519954d0f";
288#else
289 const char kChecksum[] = "9a31fb87d1c6d2346bba22d1196041cd";
290#endif // defined(OS_WIN)
291#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
292 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
293 CompareBitmap(page_bitmap.get(), 400, 400, kChecksum);
294
295 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
296 VerifySavedDocument(400, 400, kChecksum);
297}
298
Lei Zhangab41f252018-12-23 03:10:50 +0000299TEST_F(FPDFEditEmbedderTest, EmptyCreation) {
Tom Sepezd483eb42016-01-06 10:03:59 -0800300 EXPECT_TRUE(CreateEmptyDocument());
weili9b777de2016-08-19 16:19:46 -0700301 FPDF_PAGE page = FPDFPage_New(document(), 0, 640.0, 480.0);
Tom Sepezd483eb42016-01-06 10:03:59 -0800302 EXPECT_NE(nullptr, page);
Nicolas Penad9d6c292017-06-06 16:12:10 -0400303 // The FPDFPage_GenerateContent call should do nothing.
Tom Sepezd483eb42016-01-06 10:03:59 -0800304 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Tom Sepez0aec19b2016-01-07 12:22:44 -0800305 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
etienneb7712c262016-04-26 08:13:45 -0700306
Nicolas Penad9d6c292017-06-06 16:12:10 -0400307 EXPECT_THAT(GetString(), testing::MatchesRegex(std::string(
308 kExpectedPDF, sizeof(kExpectedPDF))));
weili9b777de2016-08-19 16:19:46 -0700309 FPDF_ClosePage(page);
Tom Sepezd483eb42016-01-06 10:03:59 -0800310}
thestigdc7ec032016-11-21 15:32:52 -0800311
312// Regression test for https://crbug.com/667012
Lei Zhangab41f252018-12-23 03:10:50 +0000313TEST_F(FPDFEditEmbedderTest, RasterizePDF) {
thestigdc7ec032016-11-21 15:32:52 -0800314 const char kAllBlackMd5sum[] = "5708fc5c4a8bd0abde99c8e8f0390615";
315
Lei Zhangf0542892019-01-17 18:46:27 +0000316 // Get the bitmap for the original document.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000317 ScopedFPDFBitmap orig_bitmap;
thestigdc7ec032016-11-21 15:32:52 -0800318 {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000319 ASSERT_TRUE(OpenDocument("black.pdf"));
thestigdc7ec032016-11-21 15:32:52 -0800320 FPDF_PAGE orig_page = LoadPage(0);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000321 ASSERT_TRUE(orig_page);
322 orig_bitmap = RenderLoadedPage(orig_page);
323 CompareBitmap(orig_bitmap.get(), 612, 792, kAllBlackMd5sum);
thestigdc7ec032016-11-21 15:32:52 -0800324 UnloadPage(orig_page);
325 }
326
327 // Create a new document from |orig_bitmap| and save it.
328 {
329 FPDF_DOCUMENT temp_doc = FPDF_CreateNewDocument();
330 FPDF_PAGE temp_page = FPDFPage_New(temp_doc, 0, 612, 792);
331
332 // Add the bitmap to an image object and add the image object to the output
333 // page.
Lei Zhangcbd89572017-03-15 17:35:47 -0700334 FPDF_PAGEOBJECT temp_img = FPDFPageObj_NewImageObj(temp_doc);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000335 EXPECT_TRUE(
336 FPDFImageObj_SetBitmap(&temp_page, 1, temp_img, orig_bitmap.get()));
Lei Zhangc8601bf2021-06-29 23:19:27 +0000337 static constexpr FS_MATRIX kLetterScaleMatrix{612, 0, 0, 792, 0, 0};
338 EXPECT_TRUE(FPDFPageObj_SetMatrix(temp_img, &kLetterScaleMatrix));
thestigdc7ec032016-11-21 15:32:52 -0800339 FPDFPage_InsertObject(temp_page, temp_img);
340 EXPECT_TRUE(FPDFPage_GenerateContent(temp_page));
341 EXPECT_TRUE(FPDF_SaveAsCopy(temp_doc, this, 0));
342 FPDF_ClosePage(temp_page);
343 FPDF_CloseDocument(temp_doc);
344 }
thestigdc7ec032016-11-21 15:32:52 -0800345
346 // Get the generated content. Make sure it is at least as big as the original
347 // PDF.
Lei Zhangd72fd582018-07-27 19:37:27 +0000348 EXPECT_GT(GetString().size(), 923u);
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400349 VerifySavedDocument(612, 792, kAllBlackMd5sum);
thestigdc7ec032016-11-21 15:32:52 -0800350}
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500351
Hui Yingsta929df72021-02-26 23:56:18 +0000352TEST_F(FPDFEditEmbedderTest, AddPaths) {
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500353 // Start with a blank page
Nicolas Penad03ca422017-03-06 13:54:33 -0500354 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000355 ASSERT_TRUE(page);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500356
357 // We will first add a red rectangle
358 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000359 ASSERT_TRUE(red_rect);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500360 // Expect false when trying to set colors out of range
Lei Zhang3475b482019-05-13 18:30:57 +0000361 EXPECT_FALSE(FPDFPageObj_SetStrokeColor(red_rect, 100, 100, 100, 300));
362 EXPECT_FALSE(FPDFPageObj_SetFillColor(red_rect, 200, 256, 200, 0));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500363
364 // Fill rectangle with red and insert to the page
Lei Zhang3475b482019-05-13 18:30:57 +0000365 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500366 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
Miklos Vajna491112b2018-05-30 13:30:10 +0000367
368 int fillmode = FPDF_FILLMODE_NONE;
369 FPDF_BOOL stroke = true;
370 EXPECT_TRUE(FPDFPath_GetDrawMode(red_rect, &fillmode, &stroke));
371 EXPECT_EQ(FPDF_FILLMODE_ALTERNATE, fillmode);
372 EXPECT_FALSE(stroke);
373
Lei Zhangc8601bf2021-06-29 23:19:27 +0000374 static constexpr FS_MATRIX kMatrix = {1, 2, 3, 4, 5, 6};
375 EXPECT_TRUE(FPDFPageObj_SetMatrix(red_rect, &kMatrix));
Lei Zhang8da98232019-12-11 23:29:33 +0000376
377 FS_MATRIX matrix;
Lei Zhangc8601bf2021-06-29 23:19:27 +0000378 EXPECT_TRUE(FPDFPageObj_GetMatrix(red_rect, &matrix));
Lei Zhang8da98232019-12-11 23:29:33 +0000379 EXPECT_FLOAT_EQ(1.0f, matrix.a);
380 EXPECT_FLOAT_EQ(2.0f, matrix.b);
381 EXPECT_FLOAT_EQ(3.0f, matrix.c);
382 EXPECT_FLOAT_EQ(4.0f, matrix.d);
383 EXPECT_FLOAT_EQ(5.0f, matrix.e);
384 EXPECT_FLOAT_EQ(6.0f, matrix.f);
385
386 // Set back the identity matrix.
387 matrix = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
Lei Zhangc8601bf2021-06-29 23:19:27 +0000388 EXPECT_TRUE(FPDFPageObj_SetMatrix(red_rect, &matrix));
Miklos Vajna97f4d672018-06-04 14:47:17 +0000389
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500390 FPDFPage_InsertObject(page, red_rect);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000391 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000392 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +0000393 CompareBitmap(page_bitmap.get(), 612, 792, kRedRectangleChecksum);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000394 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500395
396 // Now add to that a green rectangle with some medium alpha
397 FPDF_PAGEOBJECT green_rect = FPDFPageObj_CreateNewRect(100, 100, 40, 40);
Lei Zhang3475b482019-05-13 18:30:57 +0000398 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_rect, 0, 255, 0, 128));
Miklos Vajnaed4705b2017-04-05 09:24:50 +0200399
Miklos Vajna1ef04c92017-05-08 18:14:19 +0200400 // Make sure the type of the rectangle is a path.
401 EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(green_rect));
402
Miklos Vajnaed4705b2017-04-05 09:24:50 +0200403 // Make sure we get back the same color we set previously.
404 unsigned int R;
405 unsigned int G;
406 unsigned int B;
407 unsigned int A;
Lei Zhang3475b482019-05-13 18:30:57 +0000408 EXPECT_TRUE(FPDFPageObj_GetFillColor(green_rect, &R, &G, &B, &A));
Lei Zhangd72fd582018-07-27 19:37:27 +0000409 EXPECT_EQ(0u, R);
410 EXPECT_EQ(255u, G);
411 EXPECT_EQ(0u, B);
412 EXPECT_EQ(128u, A);
Miklos Vajnaed4705b2017-04-05 09:24:50 +0200413
Lei Zhang9b4b8df2021-06-12 06:38:48 +0000414 // Make sure the path has 5 points (1 CFX_Path::Point::Type::kMove and 4
415 // CFX_Path::Point::Type::kLine).
Miklos Vajna0150a542017-09-21 21:46:56 +0200416 ASSERT_EQ(5, FPDFPath_CountSegments(green_rect));
Miklos Vajna36eed872017-09-20 22:52:43 +0200417 // Verify actual coordinates.
418 FPDF_PATHSEGMENT segment = FPDFPath_GetPathSegment(green_rect, 0);
419 float x;
420 float y;
421 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
422 EXPECT_EQ(100, x);
423 EXPECT_EQ(100, y);
424 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
425 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
426 segment = FPDFPath_GetPathSegment(green_rect, 1);
427 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
428 EXPECT_EQ(100, x);
429 EXPECT_EQ(140, y);
430 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
431 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
432 segment = FPDFPath_GetPathSegment(green_rect, 2);
433 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
434 EXPECT_EQ(140, x);
435 EXPECT_EQ(140, y);
436 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
437 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
438 segment = FPDFPath_GetPathSegment(green_rect, 3);
439 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
440 EXPECT_EQ(140, x);
441 EXPECT_EQ(100, y);
442 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
443 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
444 segment = FPDFPath_GetPathSegment(green_rect, 4);
445 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
446 EXPECT_EQ(100, x);
447 EXPECT_EQ(100, y);
448 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
449 EXPECT_TRUE(FPDFPathSegment_GetClose(segment));
Miklos Vajna12abfd02017-09-15 07:49:03 +0200450
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500451 EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect, FPDF_FILLMODE_WINDING, 0));
452 FPDFPage_InsertObject(page, green_rect);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000453 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000454 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000455 CompareBitmap(page_bitmap.get(), 612, 792,
456 "7b0b87604594e773add528fae567a558");
457 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500458
459 // Add a black triangle.
460 FPDF_PAGEOBJECT black_path = FPDFPageObj_CreateNewPath(400, 100);
Lei Zhang3475b482019-05-13 18:30:57 +0000461 EXPECT_TRUE(FPDFPageObj_SetFillColor(black_path, 0, 0, 0, 200));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500462 EXPECT_TRUE(FPDFPath_SetDrawMode(black_path, FPDF_FILLMODE_ALTERNATE, 0));
463 EXPECT_TRUE(FPDFPath_LineTo(black_path, 400, 200));
464 EXPECT_TRUE(FPDFPath_LineTo(black_path, 300, 100));
465 EXPECT_TRUE(FPDFPath_Close(black_path));
Miklos Vajna12abfd02017-09-15 07:49:03 +0200466
Lei Zhang9b4b8df2021-06-12 06:38:48 +0000467 // Make sure the path has 3 points (1 CFX_Path::Point::Type::kMove and 2
468 // CFX_Path::Point::Type::kLine).
Miklos Vajna0150a542017-09-21 21:46:56 +0200469 ASSERT_EQ(3, FPDFPath_CountSegments(black_path));
Miklos Vajna36eed872017-09-20 22:52:43 +0200470 // Verify actual coordinates.
471 segment = FPDFPath_GetPathSegment(black_path, 0);
472 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
473 EXPECT_EQ(400, x);
474 EXPECT_EQ(100, y);
475 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
476 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
477 segment = FPDFPath_GetPathSegment(black_path, 1);
478 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
479 EXPECT_EQ(400, x);
480 EXPECT_EQ(200, y);
481 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
482 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
483 segment = FPDFPath_GetPathSegment(black_path, 2);
484 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
485 EXPECT_EQ(300, x);
486 EXPECT_EQ(100, y);
487 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
488 EXPECT_TRUE(FPDFPathSegment_GetClose(segment));
489 // Make sure out of bounds index access fails properly.
490 EXPECT_EQ(nullptr, FPDFPath_GetPathSegment(black_path, 3));
Miklos Vajna12abfd02017-09-15 07:49:03 +0200491
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500492 FPDFPage_InsertObject(page, black_path);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000493 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000494 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000495 CompareBitmap(page_bitmap.get(), 612, 792,
496 "eadc8020a14dfcf091da2688733d8806");
497 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500498
499 // Now add a more complex blue path.
500 FPDF_PAGEOBJECT blue_path = FPDFPageObj_CreateNewPath(200, 200);
Lei Zhang3475b482019-05-13 18:30:57 +0000501 EXPECT_TRUE(FPDFPageObj_SetFillColor(blue_path, 0, 0, 255, 255));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500502 EXPECT_TRUE(FPDFPath_SetDrawMode(blue_path, FPDF_FILLMODE_WINDING, 0));
503 EXPECT_TRUE(FPDFPath_LineTo(blue_path, 230, 230));
504 EXPECT_TRUE(FPDFPath_BezierTo(blue_path, 250, 250, 280, 280, 300, 300));
505 EXPECT_TRUE(FPDFPath_LineTo(blue_path, 325, 325));
506 EXPECT_TRUE(FPDFPath_LineTo(blue_path, 350, 325));
507 EXPECT_TRUE(FPDFPath_BezierTo(blue_path, 375, 330, 390, 360, 400, 400));
508 EXPECT_TRUE(FPDFPath_Close(blue_path));
509 FPDFPage_InsertObject(page, blue_path);
Hui Yingsta929df72021-02-26 23:56:18 +0000510#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
511 static constexpr char kLastChecksum[] = "ed14c60702b1489c597c7d46ece7f86d";
512#else
513 static constexpr char kLastChecksum[] = "9823e1a21bd9b72b6a442ba4f12af946";
514#endif
Lei Zhang107fa7b2018-02-09 21:48:15 +0000515 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000516 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingsta929df72021-02-26 23:56:18 +0000517 CompareBitmap(page_bitmap.get(), 612, 792, kLastChecksum);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000518 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500519
520 // Now save the result, closing the page and document
Nicolas Pena207b7272017-05-26 17:37:06 -0400521 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Nicolas Penad03ca422017-03-06 13:54:33 -0500522 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500523 FPDF_ClosePage(page);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500524
525 // Render the saved result
Hui Yingsta929df72021-02-26 23:56:18 +0000526 VerifySavedDocument(612, 792, kLastChecksum);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500527}
528
Miklos Vajna45501f32019-07-30 07:41:02 +0000529TEST_F(FPDFEditEmbedderTest, ClipPath) {
530 // Load document with a clipped rectangle.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000531 ASSERT_TRUE(OpenDocument("clip_path.pdf"));
Miklos Vajna45501f32019-07-30 07:41:02 +0000532 FPDF_PAGE page = LoadPage(0);
533 ASSERT_TRUE(page);
534
535 ASSERT_EQ(1, FPDFPage_CountObjects(page));
536
537 FPDF_PAGEOBJECT triangle = FPDFPage_GetObject(page, 0);
538 ASSERT_TRUE(triangle);
539
540 // Test that we got the expected triangle.
541 ASSERT_EQ(4, FPDFPath_CountSegments(triangle));
542
543 FPDF_PATHSEGMENT segment = FPDFPath_GetPathSegment(triangle, 0);
544 float x;
545 float y;
546 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
547 EXPECT_EQ(10, x);
548 EXPECT_EQ(10, y);
549 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
550 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
551
552 segment = FPDFPath_GetPathSegment(triangle, 1);
553 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
554 EXPECT_EQ(25, x);
555 EXPECT_EQ(40, y);
556 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
557 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
558
559 segment = FPDFPath_GetPathSegment(triangle, 2);
560 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
561 EXPECT_EQ(40, x);
562 EXPECT_EQ(10, y);
563 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
564 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
565
566 segment = FPDFPath_GetPathSegment(triangle, 3);
567 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
568 EXPECT_TRUE(FPDFPathSegment_GetClose(segment));
569
570 // Test FPDFPageObj_GetClipPath().
571 ASSERT_EQ(nullptr, FPDFPageObj_GetClipPath(nullptr));
572
573 FPDF_CLIPPATH clip_path = FPDFPageObj_GetClipPath(triangle);
574 ASSERT_TRUE(clip_path);
575
576 // Test FPDFClipPath_CountPaths().
577 ASSERT_EQ(-1, FPDFClipPath_CountPaths(nullptr));
578 ASSERT_EQ(1, FPDFClipPath_CountPaths(clip_path));
579
580 // Test FPDFClipPath_CountPathSegments().
581 ASSERT_EQ(-1, FPDFClipPath_CountPathSegments(nullptr, 0));
582 ASSERT_EQ(-1, FPDFClipPath_CountPathSegments(clip_path, -1));
583 ASSERT_EQ(-1, FPDFClipPath_CountPathSegments(clip_path, 1));
584 ASSERT_EQ(4, FPDFClipPath_CountPathSegments(clip_path, 0));
585
586 // FPDFClipPath_GetPathSegment() negative testing.
587 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(nullptr, 0, 0));
588 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, -1, 0));
589 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, 1, 0));
590 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, 0, -1));
591 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, 0, 4));
592
593 // FPDFClipPath_GetPathSegment() positive testing.
594 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 0);
595 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
596 EXPECT_EQ(10, x);
597 EXPECT_EQ(15, y);
598 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
599 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
600
601 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 1);
602 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
603 EXPECT_EQ(40, x);
604 EXPECT_EQ(15, y);
605 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
606 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
607
608 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 2);
609 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
610 EXPECT_EQ(40, x);
611 EXPECT_EQ(35, y);
612 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
613 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
614
615 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 3);
616 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
617 EXPECT_EQ(10, x);
618 EXPECT_EQ(35, y);
619 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
620 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
621
622 UnloadPage(page);
623}
624
Lei Zhang571f9322019-09-25 12:40:25 +0000625TEST_F(FPDFEditEmbedderTest, BUG_1399) {
626 // Load document with a clipped rectangle.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000627 ASSERT_TRUE(OpenDocument("bug_1399.pdf"));
Lei Zhang571f9322019-09-25 12:40:25 +0000628 FPDF_PAGE page = LoadPage(0);
629 ASSERT_TRUE(page);
630
631 ASSERT_EQ(7, FPDFPage_CountObjects(page));
632
633 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
634 ASSERT_TRUE(obj);
635
636 ASSERT_EQ(2, FPDFPath_CountSegments(obj));
637
638 FPDF_PATHSEGMENT segment = FPDFPath_GetPathSegment(obj, 0);
639 float x;
640 float y;
641 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
642 EXPECT_FLOAT_EQ(107.718f, x);
643 EXPECT_FLOAT_EQ(719.922f, y);
644 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
645 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
646
647 segment = FPDFPath_GetPathSegment(obj, 1);
648 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
649 EXPECT_FLOAT_EQ(394.718f, x);
650 EXPECT_FLOAT_EQ(719.922f, y);
651 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
652 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
653
654 FPDF_CLIPPATH clip_path = FPDFPageObj_GetClipPath(obj);
655 ASSERT_TRUE(clip_path);
656
657 EXPECT_EQ(-1, FPDFClipPath_CountPaths(clip_path));
658 EXPECT_EQ(-1, FPDFClipPath_CountPathSegments(clip_path, 0));
659 EXPECT_FALSE(FPDFClipPath_GetPathSegment(clip_path, 0, 0));
660
661 UnloadPage(page);
662}
663
Hui Yingstcb4203d2020-06-09 01:48:47 +0000664TEST_F(FPDFEditEmbedderTest, SetText) {
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000665 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000666 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000667 FPDF_PAGE page = LoadPage(0);
668 ASSERT_TRUE(page);
669
670 // Get the "Hello, world!" text object and change it.
671 ASSERT_EQ(2, FPDFPage_CountObjects(page));
672 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
673 ASSERT_TRUE(page_object);
Lei Zhangf0f67682019-04-08 17:03:21 +0000674 ScopedFPDFWideString text1 = GetFPDFWideString(L"Changed for SetText test");
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000675 EXPECT_TRUE(FPDFText_SetText(page_object, text1.get()));
676
677 // Verify the "Hello, world!" text is gone and "Changed for SetText test" is
678 // now displayed.
679 ASSERT_EQ(2, FPDFPage_CountObjects(page));
Hui Yingstcb4203d2020-06-09 01:48:47 +0000680
681#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
682#if defined(OS_WIN)
683 const char kChangedChecksum[] = "119f828345f547c68e9454418fb7d80d";
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000684#else
Hui Yingstcb4203d2020-06-09 01:48:47 +0000685 const char kChangedChecksum[] = "6bc5171f4eb329474989c6ccfa3d6303";
686#endif // defined(OS_WIN)
687#else
688#if defined(OS_WIN)
689 const char kChangedChecksum[] = "3137fdb27962671f5c3963a5e965eff5";
Lei Zhang0c03d632020-07-30 17:05:36 +0000690#elif defined(OS_APPLE)
Hui Yingstcb4203d2020-06-09 01:48:47 +0000691 const char kChangedChecksum[] = "904132275a1144ea06b0694537c80b4c";
692#else
693 const char kChangedChecksum[] = "a0c4ea6620772991f66bf7130379b08a";
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000694#endif
Hui Yingstcb4203d2020-06-09 01:48:47 +0000695#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000696 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000697 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstcb4203d2020-06-09 01:48:47 +0000698 CompareBitmap(page_bitmap.get(), 200, 200, kChangedChecksum);
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000699 }
700
701 // Now save the result.
702 EXPECT_TRUE(FPDFPage_GenerateContent(page));
703 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
704
705 UnloadPage(page);
706
707 // Re-open the file and check the changes were kept in the saved .pdf.
Lei Zhang0b494052019-01-31 21:41:15 +0000708 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000709 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +0000710 ASSERT_TRUE(saved_page);
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000711 EXPECT_EQ(2, FPDFPage_CountObjects(saved_page));
712 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000713 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstcb4203d2020-06-09 01:48:47 +0000714 CompareBitmap(page_bitmap.get(), 200, 200, kChangedChecksum);
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000715 }
716
717 CloseSavedPage(saved_page);
718 CloseSavedDocument();
719}
720
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000721TEST_F(FPDFEditEmbedderTest, SetTextKeepClippingPath) {
Daniel Hosseinianda651442020-07-17 23:30:22 +0000722 // Load document with some text, with parts clipped.
723 ASSERT_TRUE(OpenDocument("bug_1558.pdf"));
724 FPDF_PAGE page = LoadPage(0);
725 ASSERT_TRUE(page);
726
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000727#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Daniel Hosseinianda651442020-07-17 23:30:22 +0000728 static constexpr char kOriginalChecksum[] =
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000729 "1e08d555f4863ff34a90f849c9464ed2";
730#else
Daniel Hosseinianda651442020-07-17 23:30:22 +0000731#if defined(OS_WIN)
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000732 static constexpr char kOriginalChecksum[] =
Daniel Hosseinianda651442020-07-17 23:30:22 +0000733 "220bf2086398fc46ac094952b244c8d9";
Lei Zhang0c03d632020-07-30 17:05:36 +0000734#elif defined(OS_APPLE)
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000735 static constexpr char kOriginalChecksum[] =
Daniel Hosseinianda651442020-07-17 23:30:22 +0000736 "53cbaad93551ef2ccc27ddd63f2ca2b3";
737#else
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000738 static constexpr char kOriginalChecksum[] =
Daniel Hosseinianda651442020-07-17 23:30:22 +0000739 "ba1936fa8ca1e8cca108da76ff3500a6";
740#endif
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000741#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Daniel Hosseinianda651442020-07-17 23:30:22 +0000742 {
743 // When opened before any editing and saving, the clipping path is rendered.
744 ScopedFPDFBitmap original_bitmap = RenderPage(page);
745 CompareBitmap(original_bitmap.get(), 200, 200, kOriginalChecksum);
746 }
747
748 // "Change" the text in the objects to their current values to force them to
749 // regenerate when saving.
750 {
751 ScopedFPDFTextPage text_page(FPDFText_LoadPage(page));
752 ASSERT_TRUE(text_page);
753 const int obj_count = FPDFPage_CountObjects(page);
754 ASSERT_EQ(2, obj_count);
755 for (int i = 0; i < obj_count; ++i) {
756 FPDF_PAGEOBJECT text_obj = FPDFPage_GetObject(page, i);
757 ASSERT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(text_obj));
758 unsigned long size =
759 FPDFTextObj_GetText(text_obj, text_page.get(),
760 /*buffer=*/nullptr, /*length=*/0);
761 ASSERT_GT(size, 0u);
762 std::vector<FPDF_WCHAR> buffer = GetFPDFWideStringBuffer(size);
763 ASSERT_EQ(size, FPDFTextObj_GetText(text_obj, text_page.get(),
764 buffer.data(), size));
765 EXPECT_TRUE(FPDFText_SetText(text_obj, buffer.data()));
766 }
767 }
768
769 {
770 // After editing but before saving, the clipping path is retained.
771 ScopedFPDFBitmap edited_bitmap = RenderPage(page);
772 CompareBitmap(edited_bitmap.get(), 200, 200, kOriginalChecksum);
773 }
774
775 // Save the file.
776 EXPECT_TRUE(FPDFPage_GenerateContent(page));
777 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
778 UnloadPage(page);
779
780 // Open the saved copy and render it.
781 ASSERT_TRUE(OpenSavedDocument());
782 FPDF_PAGE saved_page = LoadSavedPage(0);
783 ASSERT_TRUE(saved_page);
784
785 {
Daniel Hosseinianda651442020-07-17 23:30:22 +0000786 ScopedFPDFBitmap saved_bitmap = RenderSavedPage(saved_page);
Daniel Hosseinian75efd912020-07-21 08:07:28 +0000787 CompareBitmap(saved_bitmap.get(), 200, 200, kOriginalChecksum);
Daniel Hosseinianda651442020-07-17 23:30:22 +0000788 }
789
790 CloseSavedPage(saved_page);
791 CloseSavedDocument();
792}
793
Daniel Hosseinian7b819bf2021-01-27 19:40:34 +0000794TEST_F(FPDFEditEmbedderTest, BUG_1574) {
795 // Load document with some text within a clipping path.
796 ASSERT_TRUE(OpenDocument("bug_1574.pdf"));
797 FPDF_PAGE page = LoadPage(0);
798 ASSERT_TRUE(page);
799
800#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
801 static constexpr char kOriginalChecksum[] =
802 "c17ce567e0fd2ecd14352cf56d8d574b";
803#else
804#if defined(OS_WIN)
805 static constexpr char kOriginalChecksum[] =
806 "297c5e52c38802106d570e35f94b5cfd";
807#elif defined(OS_APPLE)
808 static constexpr char kOriginalChecksum[] =
809 "6a11148c99a141eea7c2b91e6987eb97";
810#else
811 static constexpr char kOriginalChecksum[] =
812 "75b6f6da7c24f2e395edb1c7d81dc906";
813#endif
814#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
815 {
816 // When opened before any editing and saving, the text object is rendered.
817 ScopedFPDFBitmap original_bitmap = RenderPage(page);
818 CompareBitmap(original_bitmap.get(), 200, 300, kOriginalChecksum);
819 }
820
821 // "Change" the text in the objects to their current values to force them to
822 // regenerate when saving.
823 {
824 ScopedFPDFTextPage text_page(FPDFText_LoadPage(page));
825 ASSERT_TRUE(text_page);
826
827 ASSERT_EQ(2, FPDFPage_CountObjects(page));
828 FPDF_PAGEOBJECT text_obj = FPDFPage_GetObject(page, 1);
829 ASSERT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(text_obj));
830
831 unsigned long size = FPDFTextObj_GetText(text_obj, text_page.get(),
832 /*buffer=*/nullptr, /*length=*/0);
833 ASSERT_GT(size, 0u);
834 std::vector<FPDF_WCHAR> buffer = GetFPDFWideStringBuffer(size);
835 ASSERT_EQ(size, FPDFTextObj_GetText(text_obj, text_page.get(),
836 buffer.data(), size));
837 EXPECT_TRUE(FPDFText_SetText(text_obj, buffer.data()));
838 }
839
840 // Save the file.
841 EXPECT_TRUE(FPDFPage_GenerateContent(page));
842 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
843 UnloadPage(page);
844
845 // Open the saved copy and render it.
846 ASSERT_TRUE(OpenSavedDocument());
847 FPDF_PAGE saved_page = LoadSavedPage(0);
848 ASSERT_TRUE(saved_page);
849
Daniel Hosseinian7b819bf2021-01-27 19:40:34 +0000850 {
851 ScopedFPDFBitmap saved_bitmap = RenderSavedPage(saved_page);
Daniel Hosseinian91eeeb92021-01-27 19:53:24 +0000852 CompareBitmap(saved_bitmap.get(), 200, 300, kOriginalChecksum);
Daniel Hosseinian7b819bf2021-01-27 19:40:34 +0000853 }
854
855 CloseSavedPage(saved_page);
856 CloseSavedDocument();
857}
858
Hui Yingst08c40712020-04-29 01:37:35 +0000859TEST_F(FPDFEditEmbedderTest, RemovePageObject) {
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000860 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000861 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000862 FPDF_PAGE page = LoadPage(0);
863 ASSERT_TRUE(page);
864
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000865 // Show what the original file looks like.
866 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000867 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +0000868 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000869 }
870
871 // Get the "Hello, world!" text object and remove it.
872 ASSERT_EQ(2, FPDFPage_CountObjects(page));
873 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
874 ASSERT_TRUE(page_object);
875 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
876
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000877 // Verify the "Hello, world!" text is gone.
878 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000879 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +0000880 CompareBitmap(page_bitmap.get(), 200, 200, kFirstRemovedChecksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000881 }
882 ASSERT_EQ(1, FPDFPage_CountObjects(page));
883
884 UnloadPage(page);
885 FPDFPageObj_Destroy(page_object);
886}
887
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000888void CheckMarkCounts(FPDF_PAGE page,
889 int start_from,
890 int expected_object_count,
891 size_t expected_prime_count,
892 size_t expected_square_count,
893 size_t expected_greater_than_ten_count,
894 size_t expected_bounds_count) {
895 int object_count = FPDFPage_CountObjects(page);
896 ASSERT_EQ(expected_object_count, object_count);
897
898 size_t prime_count = 0;
899 size_t square_count = 0;
900 size_t greater_than_ten_count = 0;
901 size_t bounds_count = 0;
902 for (int i = 0; i < object_count; ++i) {
903 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
904
905 int mark_count = FPDFPageObj_CountMarks(page_object);
906 for (int j = 0; j < mark_count; ++j) {
907 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
908
909 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +0000910 unsigned long name_len = 999u;
911 ASSERT_TRUE(
912 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
913 EXPECT_GT(name_len, 0u);
914 EXPECT_NE(999u, name_len);
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000915 std::wstring name =
916 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
917 if (name == L"Prime") {
918 prime_count++;
919 } else if (name == L"Square") {
920 square_count++;
921 int expected_square = start_from + i;
922 EXPECT_EQ(1, FPDFPageObjMark_CountParams(mark));
923
Henrique Nakashimac3099d12018-09-18 18:08:15 +0000924 unsigned long get_param_key_return = 999u;
925 ASSERT_TRUE(FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer),
926 &get_param_key_return));
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000927 EXPECT_EQ((6u + 1u) * 2u, get_param_key_return);
928 std::wstring key =
929 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
930 EXPECT_EQ(L"Factor", key);
931
932 EXPECT_EQ(FPDF_OBJECT_NUMBER,
Henrique Nakashima94230e52018-07-11 22:02:02 +0000933 FPDFPageObjMark_GetParamValueType(mark, "Factor"));
Henrique Nakashima140dead2018-07-11 21:40:03 +0000934 int square_root;
Henrique Nakashima94230e52018-07-11 22:02:02 +0000935 EXPECT_TRUE(
936 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &square_root));
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000937 EXPECT_EQ(expected_square, square_root * square_root);
938 } else if (name == L"GreaterThanTen") {
939 greater_than_ten_count++;
940 } else if (name == L"Bounds") {
941 bounds_count++;
942 EXPECT_EQ(1, FPDFPageObjMark_CountParams(mark));
943
Henrique Nakashimac3099d12018-09-18 18:08:15 +0000944 unsigned long get_param_key_return = 999u;
945 ASSERT_TRUE(FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer),
946 &get_param_key_return));
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000947 EXPECT_EQ((8u + 1u) * 2u, get_param_key_return);
948 std::wstring key =
949 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
950 EXPECT_EQ(L"Position", key);
951
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000952 EXPECT_EQ(FPDF_OBJECT_STRING,
Henrique Nakashima94230e52018-07-11 22:02:02 +0000953 FPDFPageObjMark_GetParamValueType(mark, "Position"));
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000954 unsigned long length;
Henrique Nakashimaa3406772018-07-13 19:10:53 +0000955 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
956 mark, "Position", buffer, sizeof(buffer), &length));
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000957 ASSERT_GT(length, 0u);
Henrique Nakashima140dead2018-07-11 21:40:03 +0000958 std::wstring value =
959 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
Henrique Nakashimad8df8c32018-07-12 22:15:09 +0000960
Henrique Nakashimaa3406772018-07-13 19:10:53 +0000961 // "Position" can be "First", "Last", or "End".
Henrique Nakashimad8df8c32018-07-12 22:15:09 +0000962 if (i == 0) {
963 EXPECT_EQ((5u + 1u) * 2u, length);
964 EXPECT_EQ(L"First", value);
965 } else if (i == object_count - 1) {
Henrique Nakashimaa3406772018-07-13 19:10:53 +0000966 if (length == (4u + 1u) * 2u) {
967 EXPECT_EQ(L"Last", value);
968 } else if (length == (3u + 1u) * 2u) {
969 EXPECT_EQ(L"End", value);
970 } else {
971 FAIL();
972 }
Henrique Nakashimad8df8c32018-07-12 22:15:09 +0000973 } else {
974 FAIL();
975 }
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000976 } else {
977 FAIL();
978 }
979 }
980 }
981
982 // Expect certain number of tagged objects. The test file contains strings
983 // from 1 to 19.
984 EXPECT_EQ(expected_prime_count, prime_count);
985 EXPECT_EQ(expected_square_count, square_count);
986 EXPECT_EQ(expected_greater_than_ten_count, greater_than_ten_count);
987 EXPECT_EQ(expected_bounds_count, bounds_count);
988}
989
Lei Zhangab41f252018-12-23 03:10:50 +0000990TEST_F(FPDFEditEmbedderTest, ReadMarkedObjectsIndirectDict) {
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000991 // Load document with some text marked with an indirect property.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000992 ASSERT_TRUE(OpenDocument("text_in_page_marked_indirect.pdf"));
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000993 FPDF_PAGE page = LoadPage(0);
994 ASSERT_TRUE(page);
995
996 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
997
998 UnloadPage(page);
999}
1000
Hui Yingstf26b5f82020-11-17 05:26:03 +00001001TEST_F(FPDFEditEmbedderTest, RemoveMarkedObjectsPrime) {
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001002 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001003 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001004 FPDF_PAGE page = LoadPage(0);
1005 ASSERT_TRUE(page);
1006
1007 // Show what the original file looks like.
1008 {
Hui Yingstf26b5f82020-11-17 05:26:03 +00001009#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1010 static constexpr char kOriginalChecksum[] =
1011 "748ed321a485d246ca6260b9e30dd200";
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001012#else
Hui Yingstf26b5f82020-11-17 05:26:03 +00001013#if defined(OS_WIN)
1014 static constexpr char kOriginalChecksum[] =
1015 "00542ee435b37749c4453be63bf7bdb6";
1016#elif defined(OS_APPLE)
1017 static constexpr char kOriginalChecksum[] =
1018 "adf815e53c788a5272b4df07c610a1da";
1019#else
1020 static constexpr char kOriginalChecksum[] =
1021 "41647268d5911d049801803b15c2dfb0";
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001022#endif
Hui Yingstf26b5f82020-11-17 05:26:03 +00001023#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Lei Zhang30ff2532019-01-31 21:37:55 +00001024 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstf26b5f82020-11-17 05:26:03 +00001025 CompareBitmap(page_bitmap.get(), 200, 200, kOriginalChecksum);
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001026 }
1027
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001028 constexpr int expected_object_count = 19;
1029 CheckMarkCounts(page, 1, expected_object_count, 8, 4, 9, 1);
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001030
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001031 // Get all objects marked with "Prime"
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001032 std::vector<FPDF_PAGEOBJECT> primes;
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001033 for (int i = 0; i < expected_object_count; ++i) {
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001034 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1035
1036 int mark_count = FPDFPageObj_CountMarks(page_object);
1037 for (int j = 0; j < mark_count; ++j) {
1038 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
1039
1040 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001041 unsigned long name_len = 999u;
1042 ASSERT_TRUE(
1043 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
1044 EXPECT_GT(name_len, 0u);
1045 EXPECT_NE(999u, name_len);
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001046 std::wstring name =
1047 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1048 if (name == L"Prime") {
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001049 primes.push_back(page_object);
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001050 }
1051 }
1052 }
1053
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001054 // Remove all objects marked with "Prime".
1055 for (FPDF_PAGEOBJECT page_object : primes) {
1056 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1057 FPDFPageObj_Destroy(page_object);
1058 }
1059
1060 EXPECT_EQ(11, FPDFPage_CountObjects(page));
Hui Yingstf26b5f82020-11-17 05:26:03 +00001061#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1062 static constexpr char kNonPrimesChecksum[] =
1063 "e2927fe2b7bbb595aca2a0e19ef3f1e8";
1064 static constexpr char kNonPrimesAfterSaveChecksum[] =
1065 "e2927fe2b7bbb595aca2a0e19ef3f1e8";
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001066#else
Hui Yingstf26b5f82020-11-17 05:26:03 +00001067#if defined(OS_WIN)
1068 static constexpr char kNonPrimesChecksum[] =
1069 "86e371fdae30c2471f476631f3f93413";
1070 static constexpr char kNonPrimesAfterSaveChecksum[] =
1071 "86e371fdae30c2471f476631f3f93413";
1072#elif defined(OS_APPLE)
1073 static constexpr char kNonPrimesChecksum[] =
1074 "d29e2ddff56e0d12f340794d26796400";
1075 static constexpr char kNonPrimesAfterSaveChecksum[] =
1076 "10eff2cd0037b661496981779601fa6f";
1077#else
1078 static constexpr char kNonPrimesChecksum[] =
1079 "67ab13115d0cc34e99a1003c28047b40";
1080 static constexpr char kNonPrimesAfterSaveChecksum[] =
1081 "67ab13115d0cc34e99a1003c28047b40";
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001082#endif
Hui Yingstf26b5f82020-11-17 05:26:03 +00001083#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001084 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001085 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstf26b5f82020-11-17 05:26:03 +00001086 CompareBitmap(page_bitmap.get(), 200, 200, kNonPrimesChecksum);
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001087 }
1088
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001089 // Save the file.
1090 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1091 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001092 UnloadPage(page);
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001093
1094 // Re-open the file and check the prime marks are not there anymore.
Lei Zhang0b494052019-01-31 21:41:15 +00001095 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001096 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001097 ASSERT_TRUE(saved_page);
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001098 EXPECT_EQ(11, FPDFPage_CountObjects(saved_page));
1099
1100 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001101 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstf26b5f82020-11-17 05:26:03 +00001102 CompareBitmap(page_bitmap.get(), 200, 200, kNonPrimesAfterSaveChecksum);
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001103 }
1104
1105 CloseSavedPage(saved_page);
1106 CloseSavedDocument();
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001107}
1108
Lei Zhangab41f252018-12-23 03:10:50 +00001109TEST_F(FPDFEditEmbedderTest, RemoveMarks) {
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001110 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001111 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001112 FPDF_PAGE page = LoadPage(0);
1113 ASSERT_TRUE(page);
1114
1115 constexpr int kExpectedObjectCount = 19;
1116 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
1117
1118 // Remove all "Prime" content marks.
1119 for (int i = 0; i < kExpectedObjectCount; ++i) {
1120 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1121
1122 int mark_count = FPDFPageObj_CountMarks(page_object);
1123 for (int j = mark_count - 1; j >= 0; --j) {
1124 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
1125
1126 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001127 unsigned long name_len = 999u;
1128 ASSERT_TRUE(
1129 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
1130 EXPECT_GT(name_len, 0u);
1131 EXPECT_NE(999u, name_len);
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001132 std::wstring name =
1133 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1134 if (name == L"Prime") {
1135 // Remove mark.
1136 EXPECT_TRUE(FPDFPageObj_RemoveMark(page_object, mark));
1137
1138 // Verify there is now one fewer mark in the page object.
1139 EXPECT_EQ(mark_count - 1, FPDFPageObj_CountMarks(page_object));
1140 }
1141 }
1142 }
1143
1144 // Verify there are 0 "Prime" content marks now.
1145 CheckMarkCounts(page, 1, kExpectedObjectCount, 0, 4, 9, 1);
1146
1147 // Save the file.
1148 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1149 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1150 UnloadPage(page);
1151
1152 // Re-open the file and check the prime marks are not there anymore.
Lei Zhang0b494052019-01-31 21:41:15 +00001153 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001154 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001155 ASSERT_TRUE(saved_page);
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001156
1157 CheckMarkCounts(saved_page, 1, kExpectedObjectCount, 0, 4, 9, 1);
1158
1159 CloseSavedPage(saved_page);
1160 CloseSavedDocument();
1161}
1162
Lei Zhangab41f252018-12-23 03:10:50 +00001163TEST_F(FPDFEditEmbedderTest, RemoveMarkParam) {
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001164 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001165 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001166 FPDF_PAGE page = LoadPage(0);
1167 ASSERT_TRUE(page);
1168
1169 constexpr int kExpectedObjectCount = 19;
1170 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
1171
1172 // Remove all "Square" content marks parameters.
1173 for (int i = 0; i < kExpectedObjectCount; ++i) {
1174 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1175
1176 int mark_count = FPDFPageObj_CountMarks(page_object);
1177 for (int j = 0; j < mark_count; ++j) {
1178 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
1179
1180 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001181 unsigned long name_len = 999u;
1182 ASSERT_TRUE(
1183 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
1184 EXPECT_GT(name_len, 0u);
1185 EXPECT_NE(999u, name_len);
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001186 std::wstring name =
1187 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1188 if (name == L"Square") {
1189 // Show the mark has a "Factor" parameter.
1190 int out_value;
1191 EXPECT_TRUE(
1192 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
1193
1194 // Remove parameter.
1195 EXPECT_TRUE(FPDFPageObjMark_RemoveParam(page_object, mark, "Factor"));
1196
1197 // Verify the "Factor" parameter is gone.
1198 EXPECT_FALSE(
1199 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
1200 }
1201 }
1202 }
1203
1204 // Save the file.
1205 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1206 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1207 UnloadPage(page);
1208
1209 // Re-open the file and check the "Factor" parameters are still gone.
Lei Zhang0b494052019-01-31 21:41:15 +00001210 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001211 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001212 ASSERT_TRUE(saved_page);
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001213
1214 size_t square_count = 0;
1215 for (int i = 0; i < kExpectedObjectCount; ++i) {
1216 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(saved_page, i);
1217
1218 int mark_count = FPDFPageObj_CountMarks(page_object);
1219 for (int j = 0; j < mark_count; ++j) {
1220 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
1221
1222 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001223 unsigned long name_len = 999u;
1224 ASSERT_TRUE(
1225 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
1226 EXPECT_GT(name_len, 0u);
1227 EXPECT_NE(999u, name_len);
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001228 std::wstring name =
1229 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1230 if (name == L"Square") {
1231 // Verify the "Factor" parameter is still gone.
1232 int out_value;
1233 EXPECT_FALSE(
1234 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
1235
1236 ++square_count;
1237 }
1238 }
1239 }
1240
1241 // Verify the parameters are gone, but the marks are not.
1242 EXPECT_EQ(4u, square_count);
1243
1244 CloseSavedPage(saved_page);
1245 CloseSavedDocument();
1246}
1247
Lei Zhangab41f252018-12-23 03:10:50 +00001248TEST_F(FPDFEditEmbedderTest, MaintainMarkedObjects) {
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001249 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001250 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001251 FPDF_PAGE page = LoadPage(0);
1252 ASSERT_TRUE(page);
1253
1254 // Iterate over all objects, counting the number of times each content mark
1255 // name appears.
1256 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
1257
1258 // Remove first page object.
1259 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1260 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1261 FPDFPageObj_Destroy(page_object);
1262
1263 CheckMarkCounts(page, 2, 18, 8, 3, 9, 1);
1264
1265 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1266 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1267
1268 UnloadPage(page);
1269
Lei Zhang0b494052019-01-31 21:41:15 +00001270 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001271 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001272 ASSERT_TRUE(saved_page);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001273
1274 CheckMarkCounts(saved_page, 2, 18, 8, 3, 9, 1);
1275
1276 CloseSavedPage(saved_page);
1277 CloseSavedDocument();
1278}
1279
Lei Zhangab41f252018-12-23 03:10:50 +00001280TEST_F(FPDFEditEmbedderTest, MaintainIndirectMarkedObjects) {
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001281 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001282 ASSERT_TRUE(OpenDocument("text_in_page_marked_indirect.pdf"));
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001283 FPDF_PAGE page = LoadPage(0);
1284 ASSERT_TRUE(page);
1285
1286 // Iterate over all objects, counting the number of times each content mark
1287 // name appears.
1288 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
1289
1290 // Remove first page object.
1291 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1292 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1293 FPDFPageObj_Destroy(page_object);
1294
1295 CheckMarkCounts(page, 2, 18, 8, 3, 9, 1);
1296
1297 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1298 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1299
1300 UnloadPage(page);
1301
Lei Zhang0b494052019-01-31 21:41:15 +00001302 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001303 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001304 ASSERT_TRUE(saved_page);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001305
1306 CheckMarkCounts(saved_page, 2, 18, 8, 3, 9, 1);
1307
1308 CloseSavedPage(saved_page);
1309 CloseSavedDocument();
1310}
1311
Lei Zhangab41f252018-12-23 03:10:50 +00001312TEST_F(FPDFEditEmbedderTest, RemoveExistingPageObject) {
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001313 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001314 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001315 FPDF_PAGE page = LoadPage(0);
1316 ASSERT_TRUE(page);
1317
1318 // Get the "Hello, world!" text object and remove it.
1319 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1320 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1321 ASSERT_TRUE(page_object);
1322 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1323
1324 // Verify the "Hello, world!" text is gone.
1325 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1326
1327 // Save the file
1328 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1329 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1330 UnloadPage(page);
1331 FPDFPageObj_Destroy(page_object);
1332
1333 // Re-open the file and check the page object count is still 1.
Lei Zhang0b494052019-01-31 21:41:15 +00001334 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001335 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001336 ASSERT_TRUE(saved_page);
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001337 EXPECT_EQ(1, FPDFPage_CountObjects(saved_page));
1338 CloseSavedPage(saved_page);
1339 CloseSavedDocument();
1340}
1341
Hui Yingstcb4203d2020-06-09 01:48:47 +00001342TEST_F(FPDFEditEmbedderTest, RemoveExistingPageObjectSplitStreamsNotLonely) {
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001343 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001344 ASSERT_TRUE(OpenDocument("hello_world_split_streams.pdf"));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001345 FPDF_PAGE page = LoadPage(0);
1346 ASSERT_TRUE(page);
1347
1348 // Get the "Hello, world!" text object and remove it. There is another object
1349 // in the same stream that says "Goodbye, world!"
1350 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1351 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1352 ASSERT_TRUE(page_object);
1353 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1354
1355 // Verify the "Hello, world!" text is gone.
1356 ASSERT_EQ(2, FPDFPage_CountObjects(page));
Hui Yingstcb4203d2020-06-09 01:48:47 +00001357#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1358#if defined(OS_WIN)
1359 const char kHelloRemovedChecksum[] = "e05c7837a5cad61305d157720637f969";
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001360#else
Hui Yingstcb4203d2020-06-09 01:48:47 +00001361 const char kHelloRemovedChecksum[] = "deed7dc2754dc80930f3b05e2ac86c94";
1362#endif // defined(OS_WIN)
1363#else
1364#if defined(OS_WIN)
1365 const char kHelloRemovedChecksum[] = "a97d4c72c969ba373c2dce675d277e65";
Lei Zhang0c03d632020-07-30 17:05:36 +00001366#elif defined(OS_APPLE)
Hui Yingstcb4203d2020-06-09 01:48:47 +00001367 const char kHelloRemovedChecksum[] = "3b3b27602a86dfe5996a33c42c59885b";
1368#else
1369 const char kHelloRemovedChecksum[] = "95b92950647a2190e1230911e7a1a0e9";
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001370#endif
Hui Yingstcb4203d2020-06-09 01:48:47 +00001371#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001372 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001373 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstcb4203d2020-06-09 01:48:47 +00001374 CompareBitmap(page_bitmap.get(), 200, 200, kHelloRemovedChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001375 }
1376
1377 // Save the file
1378 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1379 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1380 UnloadPage(page);
1381 FPDFPageObj_Destroy(page_object);
1382
1383 // Re-open the file and check the page object count is still 2.
Lei Zhang0b494052019-01-31 21:41:15 +00001384 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001385 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001386 ASSERT_TRUE(saved_page);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001387
1388 EXPECT_EQ(2, FPDFPage_CountObjects(saved_page));
1389 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001390 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstcb4203d2020-06-09 01:48:47 +00001391 CompareBitmap(page_bitmap.get(), 200, 200, kHelloRemovedChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001392 }
1393
1394 CloseSavedPage(saved_page);
1395 CloseSavedDocument();
1396}
1397
Hui Yingst08c40712020-04-29 01:37:35 +00001398TEST_F(FPDFEditEmbedderTest, RemoveExistingPageObjectSplitStreamsLonely) {
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001399 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001400 ASSERT_TRUE(OpenDocument("hello_world_split_streams.pdf"));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001401 FPDF_PAGE page = LoadPage(0);
1402 ASSERT_TRUE(page);
1403
1404 // Get the "Greetings, world!" text object and remove it. This is the only
1405 // object in the stream.
1406 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1407 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 2);
1408 ASSERT_TRUE(page_object);
1409 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1410
1411 // Verify the "Greetings, world!" text is gone.
1412 ASSERT_EQ(2, FPDFPage_CountObjects(page));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001413 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001414 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001415 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001416 }
1417
1418 // Save the file
1419 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1420 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1421 UnloadPage(page);
1422 FPDFPageObj_Destroy(page_object);
1423
1424 // Re-open the file and check the page object count is still 2.
Lei Zhang0b494052019-01-31 21:41:15 +00001425 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001426 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001427 ASSERT_TRUE(saved_page);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001428
1429 EXPECT_EQ(2, FPDFPage_CountObjects(saved_page));
1430 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001431 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001432 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001433 }
1434
1435 CloseSavedPage(saved_page);
1436 CloseSavedDocument();
1437}
1438
Lei Zhangab41f252018-12-23 03:10:50 +00001439TEST_F(FPDFEditEmbedderTest, GetContentStream) {
Henrique Nakashima6eb79392018-06-12 20:27:35 +00001440 // Load document with some text split across streams.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001441 ASSERT_TRUE(OpenDocument("split_streams.pdf"));
Henrique Nakashima6eb79392018-06-12 20:27:35 +00001442 FPDF_PAGE page = LoadPage(0);
1443 ASSERT_TRUE(page);
1444
1445 // Content stream 0: page objects 0-14.
1446 // Content stream 1: page objects 15-17.
1447 // Content stream 2: page object 18.
1448 ASSERT_EQ(19, FPDFPage_CountObjects(page));
1449 for (int i = 0; i < 19; i++) {
1450 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1451 ASSERT_TRUE(page_object);
1452 CPDF_PageObject* cpdf_page_object =
1453 CPDFPageObjectFromFPDFPageObject(page_object);
1454 if (i < 15)
1455 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1456 else if (i < 18)
1457 EXPECT_EQ(1, cpdf_page_object->GetContentStream()) << i;
1458 else
1459 EXPECT_EQ(2, cpdf_page_object->GetContentStream()) << i;
1460 }
1461
1462 UnloadPage(page);
1463}
1464
Hui Yingst0d692fe2020-11-06 17:32:50 +00001465TEST_F(FPDFEditEmbedderTest, RemoveAllFromStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001466 // Load document with some text split across streams.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001467 ASSERT_TRUE(OpenDocument("split_streams.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001468 FPDF_PAGE page = LoadPage(0);
1469 ASSERT_TRUE(page);
1470
1471 // Content stream 0: page objects 0-14.
1472 // Content stream 1: page objects 15-17.
1473 // Content stream 2: page object 18.
1474 ASSERT_EQ(19, FPDFPage_CountObjects(page));
1475
1476 // Loop backwards because objects will being removed, which shifts the indexes
1477 // after the removed position.
1478 for (int i = 18; i >= 0; i--) {
1479 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1480 ASSERT_TRUE(page_object);
1481 CPDF_PageObject* cpdf_page_object =
1482 CPDFPageObjectFromFPDFPageObject(page_object);
1483
1484 // Empty content stream 1.
1485 if (cpdf_page_object->GetContentStream() == 1) {
1486 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1487 FPDFPageObj_Destroy(page_object);
1488 }
1489 }
1490
1491 // Content stream 0: page objects 0-14.
1492 // Content stream 2: page object 15.
1493 ASSERT_EQ(16, FPDFPage_CountObjects(page));
1494 for (int i = 0; i < 16; i++) {
1495 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1496 ASSERT_TRUE(page_object);
1497 CPDF_PageObject* cpdf_page_object =
1498 CPDFPageObjectFromFPDFPageObject(page_object);
1499 if (i < 15)
1500 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1501 else
1502 EXPECT_EQ(2, cpdf_page_object->GetContentStream()) << i;
1503 }
1504
1505 // Generate contents should remove the empty stream and update the page
1506 // objects' contents stream indexes.
1507 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1508
1509 // Content stream 0: page objects 0-14.
1510 // Content stream 1: page object 15.
1511 ASSERT_EQ(16, FPDFPage_CountObjects(page));
1512 for (int i = 0; i < 16; i++) {
1513 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1514 ASSERT_TRUE(page_object);
1515 CPDF_PageObject* cpdf_page_object =
1516 CPDFPageObjectFromFPDFPageObject(page_object);
1517 if (i < 15)
1518 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1519 else
1520 EXPECT_EQ(1, cpdf_page_object->GetContentStream()) << i;
1521 }
1522
Hui Yingst0d692fe2020-11-06 17:32:50 +00001523#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1524 const char kStream1RemovedChecksum[] = "89358c444a398b0b56b35738edd8fe43";
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001525#else
Hui Yingst0d692fe2020-11-06 17:32:50 +00001526#if defined(OS_WIN)
1527 const char kStream1RemovedChecksum[] = "b4140f203523e38793283a5943d8075b";
1528#elif defined(OS_APPLE)
1529 const char kStream1RemovedChecksum[] = "0e8856ca9abc7049412e64f9230c7c43";
1530#else
1531 const char kStream1RemovedChecksum[] = "e86a3efc160ede6cfcb1f59bcacf1105";
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001532#endif
Hui Yingst0d692fe2020-11-06 17:32:50 +00001533#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001534 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001535 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst0d692fe2020-11-06 17:32:50 +00001536 CompareBitmap(page_bitmap.get(), 200, 200, kStream1RemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001537 }
1538
1539 // Save the file
1540 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1541 UnloadPage(page);
1542
1543 // Re-open the file and check the page object count is still 16, and that
1544 // content stream 1 was removed.
Lei Zhang0b494052019-01-31 21:41:15 +00001545 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001546 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001547 ASSERT_TRUE(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001548
1549 // Content stream 0: page objects 0-14.
1550 // Content stream 1: page object 15.
1551 EXPECT_EQ(16, FPDFPage_CountObjects(saved_page));
1552 for (int i = 0; i < 16; i++) {
1553 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(saved_page, i);
1554 ASSERT_TRUE(page_object);
1555 CPDF_PageObject* cpdf_page_object =
1556 CPDFPageObjectFromFPDFPageObject(page_object);
1557 if (i < 15)
1558 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1559 else
1560 EXPECT_EQ(1, cpdf_page_object->GetContentStream()) << i;
1561 }
1562
1563 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001564 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingst0d692fe2020-11-06 17:32:50 +00001565 CompareBitmap(page_bitmap.get(), 200, 200, kStream1RemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001566 }
1567
1568 CloseSavedPage(saved_page);
1569 CloseSavedDocument();
1570}
1571
Lei Zhangab41f252018-12-23 03:10:50 +00001572TEST_F(FPDFEditEmbedderTest, RemoveAllFromSingleStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001573 // Load document with a single stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001574 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001575 FPDF_PAGE page = LoadPage(0);
1576 ASSERT_TRUE(page);
1577
1578 // Content stream 0: page objects 0-1.
1579 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1580
1581 // Loop backwards because objects will being removed, which shifts the indexes
1582 // after the removed position.
1583 for (int i = 1; i >= 0; 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 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1589 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1590 FPDFPageObj_Destroy(page_object);
1591 }
1592
1593 // No more objects in the stream
1594 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1595
1596 // Generate contents should remove the empty stream and update the page
1597 // objects' contents stream indexes.
1598 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1599
1600 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1601
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001602 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001603 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001604 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001605 }
1606
1607 // Save the file
1608 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1609 UnloadPage(page);
1610
1611 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001612 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001613 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001614 ASSERT_TRUE(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001615
1616 EXPECT_EQ(0, FPDFPage_CountObjects(saved_page));
1617 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001618 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001619 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001620 }
1621
1622 CloseSavedPage(saved_page);
1623 CloseSavedDocument();
1624}
1625
Hui Yingst08c40712020-04-29 01:37:35 +00001626TEST_F(FPDFEditEmbedderTest, RemoveFirstFromSingleStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001627 // Load document with a single stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001628 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001629 FPDF_PAGE page = LoadPage(0);
1630 ASSERT_TRUE(page);
1631
1632 // Content stream 0: page objects 0-1.
1633 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1634
1635 // Remove first object.
1636 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1637 ASSERT_TRUE(page_object);
1638 CPDF_PageObject* cpdf_page_object =
1639 CPDFPageObjectFromFPDFPageObject(page_object);
1640 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1641 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1642 FPDFPageObj_Destroy(page_object);
1643
1644 // One object left in the stream.
1645 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1646 page_object = FPDFPage_GetObject(page, 0);
1647 ASSERT_TRUE(page_object);
1648 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1649 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1650
1651 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1652
1653 // Still one object left in the stream.
1654 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1655 page_object = FPDFPage_GetObject(page, 0);
1656 ASSERT_TRUE(page_object);
1657 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1658 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1659
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001660 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001661 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001662 CompareBitmap(page_bitmap.get(), 200, 200, kFirstRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001663 }
1664
1665 // Save the file
1666 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1667 UnloadPage(page);
1668
1669 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001670 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001671 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001672 ASSERT_TRUE(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001673
1674 ASSERT_EQ(1, FPDFPage_CountObjects(saved_page));
1675 page_object = FPDFPage_GetObject(saved_page, 0);
1676 ASSERT_TRUE(page_object);
1677 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1678 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1679 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001680 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001681 CompareBitmap(page_bitmap.get(), 200, 200, kFirstRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001682 }
1683
1684 CloseSavedPage(saved_page);
1685 CloseSavedDocument();
1686}
1687
Hui Yingst08c40712020-04-29 01:37:35 +00001688TEST_F(FPDFEditEmbedderTest, RemoveLastFromSingleStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001689 // Load document with a single stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001690 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001691 FPDF_PAGE page = LoadPage(0);
1692 ASSERT_TRUE(page);
1693
1694 // Content stream 0: page objects 0-1.
1695 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1696
1697 // Remove last object
1698 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 1);
1699 ASSERT_TRUE(page_object);
1700 CPDF_PageObject* cpdf_page_object =
1701 CPDFPageObjectFromFPDFPageObject(page_object);
1702 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1703 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1704 FPDFPageObj_Destroy(page_object);
1705
1706 // One object left in the stream.
1707 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1708 page_object = FPDFPage_GetObject(page, 0);
1709 ASSERT_TRUE(page_object);
1710 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1711 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1712
1713 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1714
1715 // Still one object left in the stream.
1716 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1717 page_object = FPDFPage_GetObject(page, 0);
1718 ASSERT_TRUE(page_object);
1719 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1720 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1721
Hui Yingstb4baceb2020-04-28 23:46:10 +00001722 using pdfium::kHelloWorldRemovedChecksum;
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001723 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001724 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001725 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001726 }
1727
1728 // Save the file
1729 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1730 UnloadPage(page);
1731
1732 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001733 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001734 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001735 ASSERT_TRUE(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001736
1737 ASSERT_EQ(1, FPDFPage_CountObjects(saved_page));
1738 page_object = FPDFPage_GetObject(saved_page, 0);
1739 ASSERT_TRUE(page_object);
1740 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1741 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1742 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001743 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001744 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001745 }
1746
1747 CloseSavedPage(saved_page);
1748 CloseSavedDocument();
1749}
1750
Lei Zhangab41f252018-12-23 03:10:50 +00001751TEST_F(FPDFEditEmbedderTest, RemoveAllFromMultipleStreams) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001752 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001753 ASSERT_TRUE(OpenDocument("hello_world_split_streams.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001754 FPDF_PAGE page = LoadPage(0);
1755 ASSERT_TRUE(page);
1756
1757 // Content stream 0: page objects 0-1.
1758 // Content stream 1: page object 2.
1759 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1760
1761 // Loop backwards because objects will being removed, which shifts the indexes
1762 // after the removed position.
1763 for (int i = 2; i >= 0; i--) {
1764 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1765 ASSERT_TRUE(page_object);
1766 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1767 FPDFPageObj_Destroy(page_object);
1768 }
1769
1770 // No more objects in the page.
1771 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1772
1773 // Generate contents should remove the empty streams and update the page
1774 // objects' contents stream indexes.
1775 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1776
1777 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1778
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001779 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001780 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001781 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001782 }
1783
1784 // Save the file
1785 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1786 UnloadPage(page);
1787
1788 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001789 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001790 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001791 ASSERT_TRUE(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001792
1793 EXPECT_EQ(0, FPDFPage_CountObjects(saved_page));
1794 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001795 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001796 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001797 }
1798
1799 CloseSavedPage(saved_page);
1800 CloseSavedDocument();
1801}
1802
Lei Zhangab41f252018-12-23 03:10:50 +00001803TEST_F(FPDFEditEmbedderTest, InsertPageObjectAndSave) {
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001804 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001805 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001806 FPDF_PAGE page = LoadPage(0);
1807 ASSERT_TRUE(page);
1808
1809 // Add a red rectangle.
1810 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1811 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001812 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001813 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
1814 FPDFPage_InsertObject(page, red_rect);
1815
1816 // Verify the red rectangle was added.
1817 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1818
1819 // Save the file
1820 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1821 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1822 UnloadPage(page);
1823
1824 // Re-open the file and check the page object count is still 3.
Lei Zhang0b494052019-01-31 21:41:15 +00001825 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001826 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001827 ASSERT_TRUE(saved_page);
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001828 EXPECT_EQ(3, FPDFPage_CountObjects(saved_page));
1829 CloseSavedPage(saved_page);
1830 CloseSavedDocument();
1831}
1832
Lei Zhangab41f252018-12-23 03:10:50 +00001833TEST_F(FPDFEditEmbedderTest, InsertPageObjectEditAndSave) {
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001834 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001835 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001836 FPDF_PAGE page = LoadPage(0);
1837 ASSERT_TRUE(page);
1838
1839 // Add a red rectangle.
1840 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1841 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001842 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 100, 100, 255));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001843 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
1844 FPDFPage_InsertObject(page, red_rect);
1845
1846 // Verify the red rectangle was added.
1847 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1848
1849 // Generate content but change it again
1850 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhang3475b482019-05-13 18:30:57 +00001851 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001852
1853 // Save the file
1854 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1855 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1856 UnloadPage(page);
1857
1858 // Re-open the file and check the page object count is still 3.
Lei Zhang0b494052019-01-31 21:41:15 +00001859 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001860 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001861 ASSERT_TRUE(saved_page);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001862 EXPECT_EQ(3, FPDFPage_CountObjects(saved_page));
1863 CloseSavedPage(saved_page);
1864 CloseSavedDocument();
1865}
1866
Hui Yingst8b5dfb22020-07-21 17:08:30 +00001867TEST_F(FPDFEditEmbedderTest, InsertAndRemoveLargeFile) {
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001868 const int kOriginalObjectCount = 600;
1869
1870 // Load document with many objects.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001871 ASSERT_TRUE(OpenDocument("many_rectangles.pdf"));
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001872 FPDF_PAGE page = LoadPage(0);
1873 ASSERT_TRUE(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001874
1875 using pdfium::kManyRectanglesChecksum;
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001876 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001877 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001878 CompareBitmap(page_bitmap.get(), 200, 300, kManyRectanglesChecksum);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001879 }
1880
1881 // Add a black rectangle.
1882 ASSERT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(page));
1883 FPDF_PAGEOBJECT black_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001884 EXPECT_TRUE(FPDFPageObj_SetFillColor(black_rect, 0, 0, 0, 255));
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001885 EXPECT_TRUE(FPDFPath_SetDrawMode(black_rect, FPDF_FILLMODE_ALTERNATE, 0));
1886 FPDFPage_InsertObject(page, black_rect);
1887
1888 // Verify the black rectangle was added.
1889 ASSERT_EQ(kOriginalObjectCount + 1, FPDFPage_CountObjects(page));
Hui Yingst8b5dfb22020-07-21 17:08:30 +00001890#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1891 const char kPlusRectangleMD5[] = "0d3715fcfb9bd0dd25dcce60800bff47";
1892#else
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001893 const char kPlusRectangleMD5[] = "6b9396ab570754b32b04ca629e902f77";
Hui Yingst8b5dfb22020-07-21 17:08:30 +00001894#endif
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001895 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001896 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001897 CompareBitmap(page_bitmap.get(), 200, 300, kPlusRectangleMD5);
1898 }
1899
1900 // Save the file.
1901 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1902 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1903 UnloadPage(page);
1904
1905 // Re-open the file and check the rectangle added is still there.
Lei Zhang0b494052019-01-31 21:41:15 +00001906 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001907 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001908 ASSERT_TRUE(saved_page);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001909 EXPECT_EQ(kOriginalObjectCount + 1, FPDFPage_CountObjects(saved_page));
1910 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001911 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001912 CompareBitmap(page_bitmap.get(), 200, 300, kPlusRectangleMD5);
1913 }
1914
1915 // Remove the added rectangle.
1916 FPDF_PAGEOBJECT added_object =
1917 FPDFPage_GetObject(saved_page, kOriginalObjectCount);
1918 EXPECT_TRUE(FPDFPage_RemoveObject(saved_page, added_object));
1919 FPDFPageObj_Destroy(added_object);
1920 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001921 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001922 CompareBitmap(page_bitmap.get(), 200, 300, kManyRectanglesChecksum);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001923 }
1924 EXPECT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(saved_page));
1925
1926 // Save the file again.
1927 EXPECT_TRUE(FPDFPage_GenerateContent(saved_page));
1928 EXPECT_TRUE(FPDF_SaveAsCopy(saved_document_, this, 0));
1929
1930 CloseSavedPage(saved_page);
1931 CloseSavedDocument();
1932
1933 // Re-open the file (again) and check the black rectangle was removed and the
1934 // rest is intact.
Lei Zhang0b494052019-01-31 21:41:15 +00001935 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001936 saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001937 ASSERT_TRUE(saved_page);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001938 EXPECT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(saved_page));
1939 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001940 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001941 CompareBitmap(page_bitmap.get(), 200, 300, kManyRectanglesChecksum);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001942 }
1943
1944 CloseSavedPage(saved_page);
1945 CloseSavedDocument();
1946}
1947
Lei Zhangab41f252018-12-23 03:10:50 +00001948TEST_F(FPDFEditEmbedderTest, AddAndRemovePaths) {
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001949 // Start with a blank page.
1950 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
1951 ASSERT_TRUE(page);
1952
1953 // Render the blank page and verify it's a blank bitmap.
Hui Yingstb4baceb2020-04-28 23:46:10 +00001954 using pdfium::kBlankPage612By792Checksum;
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001955 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001956 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001957 CompareBitmap(page_bitmap.get(), 612, 792, kBlankPage612By792Checksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001958 }
1959 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1960
1961 // Add a red rectangle.
1962 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
1963 ASSERT_TRUE(red_rect);
Lei Zhang3475b482019-05-13 18:30:57 +00001964 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001965 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
1966 FPDFPage_InsertObject(page, red_rect);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001967 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001968 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001969 CompareBitmap(page_bitmap.get(), 612, 792, kRedRectangleChecksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001970 }
1971 EXPECT_EQ(1, FPDFPage_CountObjects(page));
1972
1973 // Remove rectangle and verify it does not render anymore and the bitmap is
1974 // back to a blank one.
1975 EXPECT_TRUE(FPDFPage_RemoveObject(page, red_rect));
1976 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001977 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001978 CompareBitmap(page_bitmap.get(), 612, 792, kBlankPage612By792Checksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001979 }
1980 EXPECT_EQ(0, FPDFPage_CountObjects(page));
1981
1982 // Trying to remove an object not in the page should return false.
1983 EXPECT_FALSE(FPDFPage_RemoveObject(page, red_rect));
1984
1985 FPDF_ClosePage(page);
1986 FPDFPageObj_Destroy(red_rect);
1987}
1988
Lei Zhangab41f252018-12-23 03:10:50 +00001989TEST_F(FPDFEditEmbedderTest, PathsPoints) {
Miklos Vajna12abfd02017-09-15 07:49:03 +02001990 CreateNewDocument();
1991 FPDF_PAGEOBJECT img = FPDFPageObj_NewImageObj(document_);
1992 // This should fail gracefully, even if img is not a path.
Miklos Vajna0150a542017-09-21 21:46:56 +02001993 ASSERT_EQ(-1, FPDFPath_CountSegments(img));
Miklos Vajna12abfd02017-09-15 07:49:03 +02001994
1995 // This should fail gracefully, even if path is NULL.
Miklos Vajna0150a542017-09-21 21:46:56 +02001996 ASSERT_EQ(-1, FPDFPath_CountSegments(nullptr));
Miklos Vajna12abfd02017-09-15 07:49:03 +02001997
Miklos Vajna36eed872017-09-20 22:52:43 +02001998 // FPDFPath_GetPathSegment() with a non-path.
1999 ASSERT_EQ(nullptr, FPDFPath_GetPathSegment(img, 0));
2000 // FPDFPath_GetPathSegment() with a NULL path.
2001 ASSERT_EQ(nullptr, FPDFPath_GetPathSegment(nullptr, 0));
2002 float x;
2003 float y;
2004 // FPDFPathSegment_GetPoint() with a NULL segment.
2005 EXPECT_FALSE(FPDFPathSegment_GetPoint(nullptr, &x, &y));
2006
2007 // FPDFPathSegment_GetType() with a NULL segment.
2008 ASSERT_EQ(FPDF_SEGMENT_UNKNOWN, FPDFPathSegment_GetType(nullptr));
2009
2010 // FPDFPathSegment_GetClose() with a NULL segment.
2011 EXPECT_FALSE(FPDFPathSegment_GetClose(nullptr));
2012
Miklos Vajna12abfd02017-09-15 07:49:03 +02002013 FPDFPageObj_Destroy(img);
2014}
2015
Hui Yingste95d5772020-08-24 23:58:26 +00002016TEST_F(FPDFEditEmbedderTest, PathOnTopOfText) {
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002017 // Load document with some text
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002018 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002019 FPDF_PAGE page = LoadPage(0);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002020 ASSERT_TRUE(page);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002021
2022 // Add an opaque rectangle on top of some of the text.
2023 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002024 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002025 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
2026 FPDFPage_InsertObject(page, red_rect);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002027
2028 // Add a transparent triangle on top of other part of the text.
2029 FPDF_PAGEOBJECT black_path = FPDFPageObj_CreateNewPath(20, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002030 EXPECT_TRUE(FPDFPageObj_SetFillColor(black_path, 0, 0, 0, 100));
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002031 EXPECT_TRUE(FPDFPath_SetDrawMode(black_path, FPDF_FILLMODE_ALTERNATE, 0));
2032 EXPECT_TRUE(FPDFPath_LineTo(black_path, 30, 80));
2033 EXPECT_TRUE(FPDFPath_LineTo(black_path, 40, 10));
2034 EXPECT_TRUE(FPDFPath_Close(black_path));
2035 FPDFPage_InsertObject(page, black_path);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002036
Hui Yingste95d5772020-08-24 23:58:26 +00002037 // Render and check the result.
Tom Sepeze08d2b12018-04-25 18:49:32 +00002038 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
Hui Yingste95d5772020-08-24 23:58:26 +00002039#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2040#if defined(OS_WIN)
2041 const char kChecksum[] = "e755a955696373e39dbebb5cb96e1338";
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002042#else
Hui Yingste95d5772020-08-24 23:58:26 +00002043 const char kChecksum[] = "d082f9756c86bb47e1abbc2b1df7138a";
2044#endif // defined(OS_WIN)
2045#else
2046#if defined(OS_WIN)
2047 const char kChecksum[] = "74dd9c393b8b2578d2b7feb032b7daad";
2048#elif defined(OS_APPLE)
2049 const char kChecksum[] = "e55bcd1facb7243dc6e16dd5f912265b";
2050#else
2051 const char kChecksum[] = "aa71b09b93b55f467f1290e5111babee";
Nicolas Pena5bcd9a32017-03-22 11:04:35 -04002052#endif
Hui Yingste95d5772020-08-24 23:58:26 +00002053#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2054 CompareBitmap(bitmap.get(), 200, 200, kChecksum);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002055 UnloadPage(page);
2056}
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002057
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002058TEST_F(FPDFEditEmbedderTest, EditOverExistingContent) {
wileyryae858aa42017-05-31 14:49:05 -05002059 // Load document with existing content
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002060 ASSERT_TRUE(OpenDocument("bug_717.pdf"));
wileyryae858aa42017-05-31 14:49:05 -05002061 FPDF_PAGE page = LoadPage(0);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002062 ASSERT_TRUE(page);
wileyryae858aa42017-05-31 14:49:05 -05002063
2064 // Add a transparent rectangle on top of the existing content
2065 FPDF_PAGEOBJECT red_rect2 = FPDFPageObj_CreateNewRect(90, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002066 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect2, 255, 0, 0, 100));
wileyryae858aa42017-05-31 14:49:05 -05002067 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect2, FPDF_FILLMODE_ALTERNATE, 0));
2068 FPDFPage_InsertObject(page, red_rect2);
2069
2070 // Add an opaque rectangle on top of the existing content
2071 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(115, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002072 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
wileyryae858aa42017-05-31 14:49:05 -05002073 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
2074 FPDFPage_InsertObject(page, red_rect);
2075
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002076#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2077 const char kOriginalChecksum[] = "1e82fbdd21490cee9d3479fe6125af67";
2078#else
2079 const char kOriginalChecksum[] = "ad04e5bd0f471a9a564fb034bd0fb073";
2080#endif
Tom Sepeze08d2b12018-04-25 18:49:32 +00002081 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002082 CompareBitmap(bitmap.get(), 612, 792, kOriginalChecksum);
wileyryae858aa42017-05-31 14:49:05 -05002083 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2084
2085 // Now save the result, closing the page and document
2086 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Nicolas Pena3ff54002017-07-05 11:55:35 -04002087 UnloadPage(page);
wileyryae858aa42017-05-31 14:49:05 -05002088
Lei Zhang0b494052019-01-31 21:41:15 +00002089 ASSERT_TRUE(OpenSavedDocument());
Lei Zhang107fa7b2018-02-09 21:48:15 +00002090 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00002091 ASSERT_TRUE(saved_page);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002092 VerifySavedRendering(saved_page, 612, 792, kOriginalChecksum);
wileyryae858aa42017-05-31 14:49:05 -05002093
2094 ClearString();
2095 // Add another opaque rectangle on top of the existing content
2096 FPDF_PAGEOBJECT green_rect = FPDFPageObj_CreateNewRect(150, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002097 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_rect, 0, 255, 0, 255));
wileyryae858aa42017-05-31 14:49:05 -05002098 EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect, FPDF_FILLMODE_ALTERNATE, 0));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002099 FPDFPage_InsertObject(saved_page, green_rect);
wileyryae858aa42017-05-31 14:49:05 -05002100
2101 // Add another transparent rectangle on top of existing content
2102 FPDF_PAGEOBJECT green_rect2 = FPDFPageObj_CreateNewRect(175, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002103 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_rect2, 0, 255, 0, 100));
wileyryae858aa42017-05-31 14:49:05 -05002104 EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect2, FPDF_FILLMODE_ALTERNATE, 0));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002105 FPDFPage_InsertObject(saved_page, green_rect2);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002106#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2107 const char kLastChecksum[] = "8705d023e5fec3499d1e30cf2bcc5dc1";
2108#else
2109 const char kLastChecksum[] = "4b5b00f824620f8c9b8801ebb98e1cdd";
2110#endif
Lei Zhangc113c7a2018-02-12 14:58:44 +00002111 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00002112 ScopedFPDFBitmap new_bitmap = RenderSavedPage(saved_page);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002113 CompareBitmap(new_bitmap.get(), 612, 792, kLastChecksum);
Lei Zhangc113c7a2018-02-12 14:58:44 +00002114 }
Lei Zhang107fa7b2018-02-09 21:48:15 +00002115 EXPECT_TRUE(FPDFPage_GenerateContent(saved_page));
wileyryae858aa42017-05-31 14:49:05 -05002116
2117 // Now save the result, closing the page and document
Lei Zhang0729be22018-02-05 21:13:51 +00002118 EXPECT_TRUE(FPDF_SaveAsCopy(saved_document_, this, 0));
Dan Sinclair04e4dc82017-10-18 12:17:14 -04002119
Lei Zhang107fa7b2018-02-09 21:48:15 +00002120 CloseSavedPage(saved_page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04002121 CloseSavedDocument();
wileyryae858aa42017-05-31 14:49:05 -05002122
2123 // Render the saved result
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002124 VerifySavedDocument(612, 792, kLastChecksum);
wileyryae858aa42017-05-31 14:49:05 -05002125}
2126
Hui Yingst041116e2021-03-01 21:27:50 +00002127// TODO(crbug.com/pdfium/1651): Fix this issue and enable the test for Skia.
2128#if defined(_SKIA_SUPPORT_)
Lei Zhang03e5e682019-09-16 19:45:55 +00002129#define MAYBE_AddStrokedPaths DISABLED_AddStrokedPaths
2130#else
2131#define MAYBE_AddStrokedPaths AddStrokedPaths
2132#endif
2133TEST_F(FPDFEditEmbedderTest, MAYBE_AddStrokedPaths) {
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002134 // Start with a blank page
Nicolas Penad03ca422017-03-06 13:54:33 -05002135 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002136
2137 // Add a large stroked rectangle (fill color should not affect it).
2138 FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(20, 20, 200, 400);
Lei Zhang3475b482019-05-13 18:30:57 +00002139 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect, 255, 0, 0, 255));
2140 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(rect, 0, 255, 0, 255));
2141 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(rect, 15.0f));
Miklos Vajna366df7f2018-05-22 14:27:29 +00002142
2143 float width = 0;
2144 EXPECT_TRUE(FPDFPageObj_GetStrokeWidth(rect, &width));
2145 EXPECT_EQ(15.0f, width);
2146
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002147 EXPECT_TRUE(FPDFPath_SetDrawMode(rect, 0, 1));
2148 FPDFPage_InsertObject(page, rect);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002149 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002150 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst041116e2021-03-01 21:27:50 +00002151#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2152 static constexpr char kChecksum_1[] = "1469acf60e7647ebeb8e1fb08c5d6c7a";
2153#else
2154 static constexpr char kChecksum_1[] = "64bd31f862a89e0a9e505a5af6efd506";
2155#endif
2156 CompareBitmap(page_bitmap.get(), 612, 792, kChecksum_1);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002157 }
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002158
2159 // Add crossed-checkmark
2160 FPDF_PAGEOBJECT check = FPDFPageObj_CreateNewPath(300, 500);
2161 EXPECT_TRUE(FPDFPath_LineTo(check, 400, 400));
2162 EXPECT_TRUE(FPDFPath_LineTo(check, 600, 600));
2163 EXPECT_TRUE(FPDFPath_MoveTo(check, 400, 600));
2164 EXPECT_TRUE(FPDFPath_LineTo(check, 600, 400));
Lei Zhang3475b482019-05-13 18:30:57 +00002165 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(check, 128, 128, 128, 180));
2166 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(check, 8.35f));
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002167 EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1));
2168 FPDFPage_InsertObject(page, check);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002169 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002170 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst041116e2021-03-01 21:27:50 +00002171#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2172 static constexpr char kChecksum_2[] = "68b3194f74abd9d471695ce1415be43f";
2173#else
2174 static constexpr char kChecksum_2[] = "4b6f3b9d25c4e194821217d5016c3724";
2175#endif
2176 CompareBitmap(page_bitmap.get(), 612, 792, kChecksum_2);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002177 }
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002178
2179 // Add stroked and filled oval-ish path.
2180 FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(250, 100);
2181 EXPECT_TRUE(FPDFPath_BezierTo(path, 180, 166, 180, 233, 250, 300));
2182 EXPECT_TRUE(FPDFPath_LineTo(path, 255, 305));
2183 EXPECT_TRUE(FPDFPath_BezierTo(path, 325, 233, 325, 166, 255, 105));
2184 EXPECT_TRUE(FPDFPath_Close(path));
Lei Zhang3475b482019-05-13 18:30:57 +00002185 EXPECT_TRUE(FPDFPageObj_SetFillColor(path, 200, 128, 128, 100));
2186 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(path, 128, 200, 128, 150));
2187 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(path, 10.5f));
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002188 EXPECT_TRUE(FPDFPath_SetDrawMode(path, FPDF_FILLMODE_ALTERNATE, 1));
2189 FPDFPage_InsertObject(page, path);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002190 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002191 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst041116e2021-03-01 21:27:50 +00002192#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2193 static constexpr char kChecksum_3[] = "ea784068651df2b9ba132ce9215e6780";
2194#else
2195 static constexpr char kChecksum_3[] = "ff3e6a22326754944cc6e56609acd73b";
2196#endif
2197 CompareBitmap(page_bitmap.get(), 612, 792, kChecksum_3);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002198 }
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002199 FPDF_ClosePage(page);
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002200}
Nicolas Pena49058402017-02-14 18:26:20 -05002201
Nicolas Pena4c48b102018-06-13 18:23:46 +00002202// Tests adding text from standard font using FPDFPageObj_NewTextObj.
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002203TEST_F(FPDFEditEmbedderTest, AddStandardFontText) {
Nicolas Pena49058402017-02-14 18:26:20 -05002204 // Start with a blank page
Nicolas Penad03ca422017-03-06 13:54:33 -05002205 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
Nicolas Pena49058402017-02-14 18:26:20 -05002206
2207 // Add some text to the page
Nicolas Penab3161852017-05-02 14:12:50 -04002208 FPDF_PAGEOBJECT text_object1 =
2209 FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
2210 EXPECT_TRUE(text_object1);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002211 ScopedFPDFWideString text1 = GetFPDFWideString(kBottomText);
Nicolas Penab3161852017-05-02 14:12:50 -04002212 EXPECT_TRUE(FPDFText_SetText(text_object1, text1.get()));
Lei Zhangcfd08172021-06-30 04:11:21 +00002213 static constexpr FS_MATRIX kMatrix1{1, 0, 0, 1, 20, 20};
2214 EXPECT_TRUE(FPDFPageObj_SetMatrix(text_object1, &kMatrix1));
Nicolas Penab3161852017-05-02 14:12:50 -04002215 FPDFPage_InsertObject(page, text_object1);
Lei Zhange039bab2019-03-18 19:57:56 +00002216 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002217 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002218 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002219 CompareBitmap(page_bitmap.get(), 612, 792, kBottomTextChecksum);
Lei Zhange039bab2019-03-18 19:57:56 +00002220
2221 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Hui Yingst3b6136a2020-06-09 00:39:33 +00002222 VerifySavedDocument(612, 792, kBottomTextChecksum);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002223 }
Nicolas Pena49058402017-02-14 18:26:20 -05002224
2225 // Try another font
Nicolas Penab3161852017-05-02 14:12:50 -04002226 FPDF_PAGEOBJECT text_object2 =
Nicolas Penad03ca422017-03-06 13:54:33 -05002227 FPDFPageObj_NewTextObj(document(), "TimesNewRomanBold", 15.0f);
Nicolas Penab3161852017-05-02 14:12:50 -04002228 EXPECT_TRUE(text_object2);
Lei Zhangf0f67682019-04-08 17:03:21 +00002229 ScopedFPDFWideString text2 =
Nicolas Penab3161852017-05-02 14:12:50 -04002230 GetFPDFWideString(L"Hi, I'm Bold. Times New Roman Bold.");
2231 EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
2232 FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 100, 600);
2233 FPDFPage_InsertObject(page, text_object2);
Lei Zhange039bab2019-03-18 19:57:56 +00002234 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002235 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002236 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002237#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2238 static constexpr char md5[] = "285cf09ca5600fc4ec061dc5ad5c6400";
Nicolas Pena49058402017-02-14 18:26:20 -05002239#else
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002240#if defined(OS_WIN)
2241 static constexpr char md5[] = "3755dd35abd4c605755369401ee85b2d";
2242#elif defined(OS_APPLE)
2243 static constexpr char md5[] = "26a516d923b0a18fbea0a24e3aca5562";
2244#else
2245 static constexpr char md5[] = "76fcc7d08aa15445efd2e2ceb7c6cc3b";
Nicolas Pena5bcd9a32017-03-22 11:04:35 -04002246#endif
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002247#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Lei Zhange039bab2019-03-18 19:57:56 +00002248 CompareBitmap(page_bitmap.get(), 612, 792, md5);
2249
2250 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2251 VerifySavedDocument(612, 792, md5);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002252 }
Nicolas Pena49058402017-02-14 18:26:20 -05002253
2254 // And some randomly transformed text
Nicolas Penab3161852017-05-02 14:12:50 -04002255 FPDF_PAGEOBJECT text_object3 =
Nicolas Penad03ca422017-03-06 13:54:33 -05002256 FPDFPageObj_NewTextObj(document(), "Courier-Bold", 20.0f);
Nicolas Penab3161852017-05-02 14:12:50 -04002257 EXPECT_TRUE(text_object3);
Lei Zhangf0f67682019-04-08 17:03:21 +00002258 ScopedFPDFWideString text3 = GetFPDFWideString(L"Can you read me? <:)>");
Nicolas Penab3161852017-05-02 14:12:50 -04002259 EXPECT_TRUE(FPDFText_SetText(text_object3, text3.get()));
2260 FPDFPageObj_Transform(text_object3, 1, 1.5, 2, 0.5, 200, 200);
2261 FPDFPage_InsertObject(page, text_object3);
Lei Zhange039bab2019-03-18 19:57:56 +00002262 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002263 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002264 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002265#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2266#if defined(OS_WIN)
2267 static constexpr char md5[] = "03c4d98eae4fda51ca67743665ab61f4";
Nicolas Pena49058402017-02-14 18:26:20 -05002268#else
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002269 static constexpr char md5[] = "177285dd8cdaf476683173fce64034ea";
2270#endif // defined(OS_WIN)
2271#else
2272#if defined(OS_WIN)
2273 static constexpr char md5[] = "5ded49fe157f89627903553771431e3d";
2274#elif defined(OS_APPLE)
2275 static constexpr char md5[] = "532024c9ded47843313bb64a060118f3";
2276#else
2277 static constexpr char md5[] = "344534539aa7c5cc78404cfff4bde7fb";
Nicolas Pena5bcd9a32017-03-22 11:04:35 -04002278#endif
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002279#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Lei Zhange039bab2019-03-18 19:57:56 +00002280 CompareBitmap(page_bitmap.get(), 612, 792, md5);
2281
2282 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2283 VerifySavedDocument(612, 792, md5);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002284 }
Nicolas Pena49058402017-02-14 18:26:20 -05002285
Lei Zhang8da98232019-12-11 23:29:33 +00002286 FS_MATRIX matrix;
Lei Zhangc8601bf2021-06-29 23:19:27 +00002287 EXPECT_TRUE(FPDFPageObj_GetMatrix(text_object3, &matrix));
Lei Zhang8da98232019-12-11 23:29:33 +00002288 EXPECT_FLOAT_EQ(1.0f, matrix.a);
2289 EXPECT_FLOAT_EQ(1.5f, matrix.b);
2290 EXPECT_FLOAT_EQ(2.0f, matrix.c);
2291 EXPECT_FLOAT_EQ(0.5f, matrix.d);
2292 EXPECT_FLOAT_EQ(200.0f, matrix.e);
2293 EXPECT_FLOAT_EQ(200.0f, matrix.f);
Miklos Vajnac765d2a2018-06-19 15:45:42 +00002294
Miklos Vajnad6d7ca72021-06-22 16:27:21 +00002295 EXPECT_FALSE(FPDFTextObj_GetFontSize(nullptr, nullptr));
2296 float size = 0;
2297 EXPECT_TRUE(FPDFTextObj_GetFontSize(text_object3, &size));
2298 EXPECT_EQ(20, size);
Miklos Vajna8625d3b2018-06-26 15:12:48 +00002299
Nicolas Pena49058402017-02-14 18:26:20 -05002300 // TODO(npm): Why are there issues with text rotated by 90 degrees?
2301 // TODO(npm): FPDF_SaveAsCopy not giving the desired result after this.
2302 FPDF_ClosePage(page);
Nicolas Pena49058402017-02-14 18:26:20 -05002303}
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002304
Lei Zhang20c52152021-06-18 20:37:10 +00002305TEST_F(FPDFEditEmbedderTest, AddStandardFontTextOfSizeZero) {
2306 // Start with a blank page
2307 ScopedFPDFPage page(FPDFPage_New(CreateNewDocument(), 0, 612, 792));
2308
2309 // Add some text of size 0 to the page.
2310 FPDF_PAGEOBJECT text_object =
2311 FPDFPageObj_NewTextObj(document(), "Arial", 0.0f);
2312 EXPECT_TRUE(text_object);
2313 ScopedFPDFWideString text = GetFPDFWideString(kBottomText);
2314 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2315 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 20, 20);
2316
Miklos Vajnad6d7ca72021-06-22 16:27:21 +00002317 float size = -1; // Make sure 'size' gets changed.
2318 EXPECT_TRUE(FPDFTextObj_GetFontSize(text_object, &size));
2319 EXPECT_EQ(0.0f, size);
Lei Zhang20c52152021-06-18 20:37:10 +00002320
2321 FPDFPage_InsertObject(page.get(), text_object);
2322 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
2323 {
2324 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
2325 CompareBitmap(page_bitmap.get(), 612, 792,
2326 pdfium::kBlankPage612By792Checksum);
2327
2328 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2329 VerifySavedDocument(612, 792, pdfium::kBlankPage612By792Checksum);
2330 }
2331}
2332
Daniel Hosseinian8cb6a652019-12-18 00:50:41 +00002333TEST_F(FPDFEditEmbedderTest, GetTextRenderMode) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002334 ASSERT_TRUE(OpenDocument("text_render_mode.pdf"));
Miklos Vajna1448cc12018-07-03 13:52:33 +00002335 FPDF_PAGE page = LoadPage(0);
2336 ASSERT_TRUE(page);
2337 ASSERT_EQ(2, FPDFPage_CountObjects(page));
2338
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002339 EXPECT_EQ(FPDF_TEXTRENDERMODE_UNKNOWN,
Daniel Hosseinian8cb6a652019-12-18 00:50:41 +00002340 FPDFTextObj_GetTextRenderMode(nullptr));
Miklos Vajna1448cc12018-07-03 13:52:33 +00002341
2342 FPDF_PAGEOBJECT fill = FPDFPage_GetObject(page, 0);
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002343 EXPECT_EQ(FPDF_TEXTRENDERMODE_FILL, FPDFTextObj_GetTextRenderMode(fill));
Miklos Vajna1448cc12018-07-03 13:52:33 +00002344
2345 FPDF_PAGEOBJECT stroke = FPDFPage_GetObject(page, 1);
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002346 EXPECT_EQ(FPDF_TEXTRENDERMODE_STROKE, FPDFTextObj_GetTextRenderMode(stroke));
2347
2348 UnloadPage(page);
2349}
2350
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002351TEST_F(FPDFEditEmbedderTest, SetTextRenderMode) {
Hui Yingst609f7d62020-04-23 23:14:13 +00002352#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002353 const char kOriginalChecksum[] = "4960c720a6cdb7b2b16be809cce58aff";
2354 const char kStrokeChecksum[] = "4c099cf9abc1565806bd7cd1cca5ac1a";
Hui Yingst609f7d62020-04-23 23:14:13 +00002355#else
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002356#if defined(OS_WIN)
2357 const char kOriginalChecksum[] = "de6e86bad3e9fda753a8471a45cfbb58";
2358#elif defined(OS_APPLE)
2359 const char kOriginalChecksum[] = "2453a9a524ee3f5f525dd21345ec4d81";
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002360#else
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002361 const char kOriginalChecksum[] = "5a012d2920ac075c39ffa9437ea42faa";
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002362#endif
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002363 const char kStrokeChecksum[] = "412e52e621b46bd77baf2162e1fb1a1d";
2364#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002365
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002366 {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002367 ASSERT_TRUE(OpenDocument("text_render_mode.pdf"));
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002368 FPDF_PAGE page = LoadPage(0);
2369 ASSERT_TRUE(page);
2370 ASSERT_EQ(2, FPDFPage_CountObjects(page));
2371
2372 // Check the bitmap
2373 {
2374 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002375 CompareBitmap(page_bitmap.get(), 612, 446, kOriginalChecksum);
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002376 }
2377
2378 // Cannot set on a null object.
2379 EXPECT_FALSE(
2380 FPDFTextObj_SetTextRenderMode(nullptr, FPDF_TEXTRENDERMODE_UNKNOWN));
2381 EXPECT_FALSE(
2382 FPDFTextObj_SetTextRenderMode(nullptr, FPDF_TEXTRENDERMODE_INVISIBLE));
2383
2384 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
2385 ASSERT_TRUE(page_object);
2386 EXPECT_EQ(FPDF_TEXTRENDERMODE_FILL,
2387 FPDFTextObj_GetTextRenderMode(page_object));
2388
2389 // Cannot set UNKNOWN as a render mode.
2390 EXPECT_FALSE(FPDFTextObj_SetTextRenderMode(page_object,
2391 FPDF_TEXTRENDERMODE_UNKNOWN));
2392
2393 EXPECT_TRUE(
2394 FPDFTextObj_SetTextRenderMode(page_object, FPDF_TEXTRENDERMODE_STROKE));
2395 EXPECT_EQ(FPDF_TEXTRENDERMODE_STROKE,
2396 FPDFTextObj_GetTextRenderMode(page_object));
2397
2398 // Check that bitmap displays changed content
2399 {
2400 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002401 CompareBitmap(page_bitmap.get(), 612, 446, kStrokeChecksum);
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002402 }
2403
Daniel Hosseinianafd27502020-07-01 04:59:03 +00002404 // Save a copy.
2405 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2406 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2407
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002408 UnloadPage(page);
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002409 }
Miklos Vajna1448cc12018-07-03 13:52:33 +00002410
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002411 {
Daniel Hosseinianafd27502020-07-01 04:59:03 +00002412 // Open the saved copy and render it. Check that the changed text render
2413 // mode is kept in the saved copy.
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002414 ASSERT_TRUE(OpenSavedDocument());
2415 FPDF_PAGE saved_page = LoadSavedPage(0);
2416 ASSERT_TRUE(saved_page);
2417
2418 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(saved_page, 0);
2419 EXPECT_TRUE(page_object);
Daniel Hosseinianafd27502020-07-01 04:59:03 +00002420 EXPECT_EQ(FPDF_TEXTRENDERMODE_STROKE,
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002421 FPDFTextObj_GetTextRenderMode(page_object));
2422
2423 ScopedFPDFBitmap bitmap = RenderSavedPage(saved_page);
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002424 CompareBitmap(bitmap.get(), 612, 446, kStrokeChecksum);
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002425
2426 CloseSavedPage(saved_page);
2427 CloseSavedDocument();
2428 }
Miklos Vajna1448cc12018-07-03 13:52:33 +00002429}
2430
Lei Zhang4363dab2021-06-24 19:23:09 +00002431TEST_F(FPDFEditEmbedderTest, GetTextFontName) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002432 ASSERT_TRUE(OpenDocument("text_font.pdf"));
Miklos Vajna53d4f0a2018-08-01 01:28:49 +00002433 FPDF_PAGE page = LoadPage(0);
2434 ASSERT_TRUE(page);
2435 ASSERT_EQ(1, FPDFPage_CountObjects(page));
2436
2437 // FPDFTextObj_GetFontName() positive testing.
2438 FPDF_PAGEOBJECT text = FPDFPage_GetObject(page, 0);
2439 unsigned long size = FPDFTextObj_GetFontName(text, nullptr, 0);
2440 const char kExpectedFontName[] = "Liberation Serif";
2441 ASSERT_EQ(sizeof(kExpectedFontName), size);
2442 std::vector<char> font_name(size);
2443 ASSERT_EQ(size, FPDFTextObj_GetFontName(text, font_name.data(), size));
2444 ASSERT_STREQ(kExpectedFontName, font_name.data());
2445
2446 // FPDFTextObj_GetFontName() negative testing.
2447 ASSERT_EQ(0U, FPDFTextObj_GetFontName(nullptr, nullptr, 0));
2448
2449 font_name.resize(2);
2450 font_name[0] = 'x';
2451 font_name[1] = '\0';
2452 size = FPDFTextObj_GetFontName(text, font_name.data(), font_name.size());
2453 ASSERT_EQ(sizeof(kExpectedFontName), size);
2454 ASSERT_EQ(std::string("x"), std::string(font_name.data()));
2455
2456 UnloadPage(page);
2457}
2458
Lei Zhang4363dab2021-06-24 19:23:09 +00002459TEST_F(FPDFEditEmbedderTest, FormGetObjects) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002460 ASSERT_TRUE(OpenDocument("form_object.pdf"));
Miklos Vajnab66077d2018-07-11 13:25:02 +00002461 FPDF_PAGE page = LoadPage(0);
2462 ASSERT_TRUE(page);
2463 ASSERT_EQ(1, FPDFPage_CountObjects(page));
2464
2465 FPDF_PAGEOBJECT form = FPDFPage_GetObject(page, 0);
Lei Zhang4363dab2021-06-24 19:23:09 +00002466 ASSERT_EQ(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(form));
Miklos Vajnab66077d2018-07-11 13:25:02 +00002467 ASSERT_EQ(-1, FPDFFormObj_CountObjects(nullptr));
2468 ASSERT_EQ(2, FPDFFormObj_CountObjects(form));
2469
Miklos Vajna1d273f12018-07-16 19:20:36 +00002470 // FPDFFormObj_GetObject() positive testing.
2471 FPDF_PAGEOBJECT text1 = FPDFFormObj_GetObject(form, 0);
2472 ASSERT_TRUE(text1);
2473 float left = 0;
2474 float bottom = 0;
2475 float right = 0;
2476 float top = 0;
2477 ASSERT_TRUE(FPDFPageObj_GetBounds(text1, &left, &bottom, &right, &top));
2478 ASSERT_EQ(271, static_cast<int>(top));
2479
2480 FPDF_PAGEOBJECT text2 = FPDFFormObj_GetObject(form, 1);
2481 ASSERT_TRUE(text2);
2482 ASSERT_TRUE(FPDFPageObj_GetBounds(text2, &left, &bottom, &right, &top));
2483 ASSERT_EQ(221, static_cast<int>(top));
2484
2485 // FPDFFormObj_GetObject() negative testing.
2486 ASSERT_EQ(nullptr, FPDFFormObj_GetObject(nullptr, 0));
2487 ASSERT_EQ(nullptr, FPDFFormObj_GetObject(form, -1));
2488 ASSERT_EQ(nullptr, FPDFFormObj_GetObject(form, 2));
2489
Lei Zhangc8601bf2021-06-29 23:19:27 +00002490 // FPDFPageObj_GetMatrix() positive testing for forms.
Lei Zhang8da98232019-12-11 23:29:33 +00002491 static constexpr FS_MATRIX kMatrix = {1.0f, 1.5f, 2.0f, 2.5f, 100.0f, 200.0f};
Lei Zhang2193da92021-06-30 01:03:07 +00002492 EXPECT_TRUE(FPDFPageObj_SetMatrix(form, &kMatrix));
Miklos Vajna46b43732018-08-14 19:15:43 +00002493
Lei Zhang8da98232019-12-11 23:29:33 +00002494 FS_MATRIX matrix;
Lei Zhangc8601bf2021-06-29 23:19:27 +00002495 EXPECT_TRUE(FPDFPageObj_GetMatrix(form, &matrix));
Lei Zhang8da98232019-12-11 23:29:33 +00002496 EXPECT_FLOAT_EQ(kMatrix.a, matrix.a);
2497 EXPECT_FLOAT_EQ(kMatrix.b, matrix.b);
2498 EXPECT_FLOAT_EQ(kMatrix.c, matrix.c);
2499 EXPECT_FLOAT_EQ(kMatrix.d, matrix.d);
2500 EXPECT_FLOAT_EQ(kMatrix.e, matrix.e);
2501 EXPECT_FLOAT_EQ(kMatrix.f, matrix.f);
Miklos Vajna46b43732018-08-14 19:15:43 +00002502
Lei Zhangc8601bf2021-06-29 23:19:27 +00002503 // FPDFPageObj_GetMatrix() negative testing for forms.
2504 EXPECT_FALSE(FPDFPageObj_GetMatrix(form, nullptr));
Miklos Vajna46b43732018-08-14 19:15:43 +00002505
Miklos Vajnab66077d2018-07-11 13:25:02 +00002506 UnloadPage(page);
2507}
2508
Lei Zhang4363dab2021-06-24 19:23:09 +00002509TEST_F(FPDFEditEmbedderTest, ModifyFormObject) {
2510#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2511#if defined(OS_WIN)
2512 const char kOrigChecksum[] = "d511cae0c8ec3e7b2e7b672485a45859";
2513#else
2514 const char kOrigChecksum[] = "6332486c11a830d52163e453cac3f0f7";
2515#endif // defined(OS_WIN)
2516 const char kNewChecksum[] = "9851fb1b59d91655ac8961ac89f383ae";
2517#else
2518#if defined(OS_WIN)
2519 const char kOrigChecksum[] = "9993d8fd85dfc1f9522c4e5f1533ed78";
2520 const char kNewChecksum[] = "ba6450c9060786c5aca3b7552ba7ec9e";
2521#elif defined(OS_APPLE)
2522 const char kOrigChecksum[] = "98c13e90ec592eea79b6458c0ca2822b";
2523 const char kNewChecksum[] = "8cbad8c9281e1f3bac2306a5beb1fdcd";
2524#else
2525 const char kOrigChecksum[] = "26e65fb47da5674d1b7284932c3c94d6";
2526 const char kNewChecksum[] = "fd408e99373b275316f7816ae8d35842";
2527#endif // defined(OS_WIN)
2528#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2529
2530 ASSERT_TRUE(OpenDocument("form_object.pdf"));
2531 FPDF_PAGE page = LoadPage(0);
2532 ASSERT_TRUE(page);
2533 ASSERT_EQ(1, FPDFPage_CountObjects(page));
2534
2535 {
2536 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
2537 CompareBitmap(bitmap.get(), 62, 69, kOrigChecksum);
2538 }
2539
2540 FPDF_PAGEOBJECT form = FPDFPage_GetObject(page, 0);
2541 ASSERT_EQ(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(form));
2542
Lei Zhang651113b2021-06-25 20:03:25 +00002543 FPDFPageObj_Transform(form, 0.5, 0, 0, 0.5, 0, 0);
Lei Zhang4363dab2021-06-24 19:23:09 +00002544 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2545
2546 {
2547 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
2548 CompareBitmap(bitmap.get(), 62, 69, kNewChecksum);
2549 }
2550
Lei Zhang4363dab2021-06-24 19:23:09 +00002551 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhangac7f0e12021-06-24 19:38:00 +00002552 VerifySavedDocument(62, 69, kNewChecksum);
Lei Zhang4363dab2021-06-24 19:23:09 +00002553
2554 UnloadPage(page);
2555}
2556
Nicolas Pena4c48b102018-06-13 18:23:46 +00002557// Tests adding text from standard font using FPDFText_LoadStandardFont.
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002558TEST_F(FPDFEditEmbedderTest, AddStandardFontText2) {
Nicolas Pena4c48b102018-06-13 18:23:46 +00002559 // Start with a blank page
2560 ScopedFPDFPage page(FPDFPage_New(CreateNewDocument(), 0, 612, 792));
2561
2562 // Load a standard font.
Tom Sepezffff6c52019-07-30 21:56:19 +00002563 ScopedFPDFFont font(FPDFText_LoadStandardFont(document(), "Helvetica"));
Nicolas Pena4c48b102018-06-13 18:23:46 +00002564 ASSERT_TRUE(font);
2565
2566 // Add some text to the page.
2567 FPDF_PAGEOBJECT text_object =
Tom Sepezffff6c52019-07-30 21:56:19 +00002568 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
Nicolas Pena4c48b102018-06-13 18:23:46 +00002569 EXPECT_TRUE(text_object);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002570 ScopedFPDFWideString text = GetFPDFWideString(kBottomText);
Nicolas Pena4c48b102018-06-13 18:23:46 +00002571 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2572 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 20, 20);
2573 FPDFPage_InsertObject(page.get(), text_object);
Lei Zhang30ff2532019-01-31 21:37:55 +00002574 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
Hui Yingst3b6136a2020-06-09 00:39:33 +00002575 CompareBitmap(page_bitmap.get(), 612, 792, kBottomTextChecksum);
Nicolas Pena4c48b102018-06-13 18:23:46 +00002576}
2577
Lei Zhangab41f252018-12-23 03:10:50 +00002578TEST_F(FPDFEditEmbedderTest, LoadStandardFonts) {
Nicolas Pena4c48b102018-06-13 18:23:46 +00002579 CreateNewDocument();
Lei Zhang590f4242019-05-15 20:57:26 +00002580 static constexpr const char* kStandardFontNames[] = {
Lei Zhangd72fd582018-07-27 19:37:27 +00002581 "Arial",
2582 "Arial-Bold",
2583 "Arial-BoldItalic",
2584 "Arial-Italic",
2585 "Courier",
2586 "Courier-BoldOblique",
2587 "Courier-Oblique",
2588 "Courier-Bold",
2589 "CourierNew",
2590 "CourierNew-Bold",
2591 "CourierNew-BoldItalic",
2592 "CourierNew-Italic",
2593 "Helvetica",
2594 "Helvetica-Bold",
2595 "Helvetica-BoldOblique",
2596 "Helvetica-Oblique",
2597 "Symbol",
2598 "TimesNewRoman",
2599 "TimesNewRoman-Bold",
2600 "TimesNewRoman-BoldItalic",
2601 "TimesNewRoman-Italic",
2602 "ZapfDingbats"};
Lei Zhang590f4242019-05-15 20:57:26 +00002603 for (const char* font_name : kStandardFontNames) {
Tom Sepezffff6c52019-07-30 21:56:19 +00002604 ScopedFPDFFont font(FPDFText_LoadStandardFont(document(), font_name));
Nicolas Pena4c48b102018-06-13 18:23:46 +00002605 EXPECT_TRUE(font) << font_name << " should be considered a standard font.";
2606 }
Lei Zhang590f4242019-05-15 20:57:26 +00002607 static constexpr const char* kNotStandardFontNames[] = {
Nicolas Pena4c48b102018-06-13 18:23:46 +00002608 "Abcdefg", "ArialB", "Arial-Style",
2609 "Font Name", "FontArial", "NotAStandardFontName",
2610 "TestFontName", "Quack", "Symbol-Italic",
2611 "Zapf"};
Lei Zhang590f4242019-05-15 20:57:26 +00002612 for (const char* font_name : kNotStandardFontNames) {
Tom Sepezffff6c52019-07-30 21:56:19 +00002613 ScopedFPDFFont font(FPDFText_LoadStandardFont(document(), font_name));
Nicolas Pena4c48b102018-06-13 18:23:46 +00002614 EXPECT_FALSE(font) << font_name
2615 << " should not be considered a standard font.";
2616 }
2617}
2618
Lei Zhangab41f252018-12-23 03:10:50 +00002619TEST_F(FPDFEditEmbedderTest, GraphicsData) {
Nicolas Pena603a31d2017-06-14 11:41:18 -04002620 // New page
Tom Sepeze08d2b12018-04-25 18:49:32 +00002621 ScopedFPDFPage page(FPDFPage_New(CreateNewDocument(), 0, 612, 792));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002622
2623 // Create a rect with nontrivial graphics
2624 FPDF_PAGEOBJECT rect1 = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
2625 FPDFPageObj_SetBlendMode(rect1, "Color");
2626 FPDFPage_InsertObject(page.get(), rect1);
2627 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
2628
2629 // Check that the ExtGState was created
Lei Zhang107fa7b2018-02-09 21:48:15 +00002630 CPDF_Page* cpage = CPDFPageFromFPDFPage(page.get());
Tom Sepezc8155092021-04-26 23:37:42 +00002631 const CPDF_Dictionary* graphics_dict =
2632 cpage->GetResources()->GetDictFor("ExtGState");
Nicolas Pena603a31d2017-06-14 11:41:18 -04002633 ASSERT_TRUE(graphics_dict);
Lei Zhangf40380f2018-10-12 18:31:51 +00002634 EXPECT_EQ(2u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002635
2636 // Add a text object causing no change to the graphics dictionary
2637 FPDF_PAGEOBJECT text1 = FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
2638 // Only alpha, the last component, matters for the graphics dictionary. And
2639 // the default value is 255.
Lei Zhang3475b482019-05-13 18:30:57 +00002640 EXPECT_TRUE(FPDFPageObj_SetFillColor(text1, 100, 100, 100, 255));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002641 FPDFPage_InsertObject(page.get(), text1);
2642 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002643 EXPECT_EQ(2u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002644
2645 // Add a text object increasing the size of the graphics dictionary
2646 FPDF_PAGEOBJECT text2 =
2647 FPDFPageObj_NewTextObj(document(), "Times-Roman", 12.0f);
2648 FPDFPage_InsertObject(page.get(), text2);
2649 FPDFPageObj_SetBlendMode(text2, "Darken");
Lei Zhang3475b482019-05-13 18:30:57 +00002650 EXPECT_TRUE(FPDFPageObj_SetFillColor(text2, 0, 0, 255, 150));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002651 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002652 EXPECT_EQ(3u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002653
2654 // Add a path that should reuse graphics
Nicolas Penace67be42017-06-14 14:52:49 -04002655 FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(400, 100);
Nicolas Pena603a31d2017-06-14 11:41:18 -04002656 FPDFPageObj_SetBlendMode(path, "Darken");
Lei Zhang3475b482019-05-13 18:30:57 +00002657 EXPECT_TRUE(FPDFPageObj_SetFillColor(path, 200, 200, 100, 150));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002658 FPDFPage_InsertObject(page.get(), path);
2659 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002660 EXPECT_EQ(3u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002661
2662 // Add a rect increasing the size of the graphics dictionary
2663 FPDF_PAGEOBJECT rect2 = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
2664 FPDFPageObj_SetBlendMode(rect2, "Darken");
Lei Zhang3475b482019-05-13 18:30:57 +00002665 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect2, 0, 0, 255, 150));
2666 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(rect2, 0, 0, 0, 200));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002667 FPDFPage_InsertObject(page.get(), rect2);
2668 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002669 EXPECT_EQ(4u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002670}
2671
Lei Zhangab41f252018-12-23 03:10:50 +00002672TEST_F(FPDFEditEmbedderTest, DoubleGenerating) {
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002673 // Start with a blank page
Nicolas Penad03ca422017-03-06 13:54:33 -05002674 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002675
2676 // Add a red rectangle with some non-default alpha
2677 FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
Lei Zhang3475b482019-05-13 18:30:57 +00002678 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect, 255, 0, 0, 128));
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002679 EXPECT_TRUE(FPDFPath_SetDrawMode(rect, FPDF_FILLMODE_WINDING, 0));
2680 FPDFPage_InsertObject(page, rect);
2681 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2682
2683 // Check the ExtGState
Lei Zhang107fa7b2018-02-09 21:48:15 +00002684 CPDF_Page* cpage = CPDFPageFromFPDFPage(page);
Tom Sepezc8155092021-04-26 23:37:42 +00002685 const CPDF_Dictionary* graphics_dict =
2686 cpage->GetResources()->GetDictFor("ExtGState");
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002687 ASSERT_TRUE(graphics_dict);
Lei Zhangf40380f2018-10-12 18:31:51 +00002688 EXPECT_EQ(2u, graphics_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002689
2690 // Check the bitmap
Lei Zhang107fa7b2018-02-09 21:48:15 +00002691 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002692 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002693 CompareBitmap(page_bitmap.get(), 612, 792,
2694 "5384da3406d62360ffb5cac4476fff1c");
2695 }
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002696
2697 // Never mind, my new favorite color is blue, increase alpha
Lei Zhang3475b482019-05-13 18:30:57 +00002698 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect, 0, 0, 255, 180));
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002699 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhangf40380f2018-10-12 18:31:51 +00002700 EXPECT_EQ(3u, graphics_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002701
2702 // Check that bitmap displays changed content
Lei Zhang107fa7b2018-02-09 21:48:15 +00002703 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002704 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002705 CompareBitmap(page_bitmap.get(), 612, 792,
2706 "2e51656f5073b0bee611d9cd086aa09c");
2707 }
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002708
2709 // And now generate, without changes
2710 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhangf40380f2018-10-12 18:31:51 +00002711 EXPECT_EQ(3u, graphics_dict->size());
Lei Zhang107fa7b2018-02-09 21:48:15 +00002712 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002713 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002714 CompareBitmap(page_bitmap.get(), 612, 792,
2715 "2e51656f5073b0bee611d9cd086aa09c");
2716 }
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002717
2718 // Add some text to the page
Nicolas Penab3161852017-05-02 14:12:50 -04002719 FPDF_PAGEOBJECT text_object =
2720 FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
Lei Zhangf0f67682019-04-08 17:03:21 +00002721 ScopedFPDFWideString text =
Nicolas Penab3161852017-05-02 14:12:50 -04002722 GetFPDFWideString(L"Something something #text# something");
2723 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2724 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 300, 300);
2725 FPDFPage_InsertObject(page, text_object);
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002726 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Tom Sepezc8155092021-04-26 23:37:42 +00002727 const CPDF_Dictionary* font_dict = cpage->GetResources()->GetDictFor("Font");
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002728 ASSERT_TRUE(font_dict);
Lei Zhangf40380f2018-10-12 18:31:51 +00002729 EXPECT_EQ(1u, font_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002730
2731 // Generate yet again, check dicts are reasonably sized
2732 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhangf40380f2018-10-12 18:31:51 +00002733 EXPECT_EQ(3u, graphics_dict->size());
2734 EXPECT_EQ(1u, font_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002735 FPDF_ClosePage(page);
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002736}
Nicolas Penabe90aae2017-02-27 10:41:41 -05002737
Lei Zhangab41f252018-12-23 03:10:50 +00002738TEST_F(FPDFEditEmbedderTest, LoadSimpleType1Font) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002739 CreateNewDocument();
2740 // TODO(npm): use other fonts after disallowing loading any font as any type
Tom Sepezffff6c52019-07-30 21:56:19 +00002741 RetainPtr<CPDF_Font> stock_font =
Nicolas Penad03ca422017-03-06 13:54:33 -05002742 CPDF_Font::GetStockFont(cpdf_doc(), "Times-Bold");
Tom Sepez20c41a52018-08-29 23:53:53 +00002743 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2744 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2745 FPDF_FONT_TYPE1, false));
Nicolas Penab3161852017-05-02 14:12:50 -04002746 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002747 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002748 EXPECT_TRUE(typed_font->IsType1Font());
Nicolas Penabe90aae2017-02-27 10:41:41 -05002749
Lei Zhang710fa992018-05-25 16:24:48 +00002750 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002751 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2752 EXPECT_EQ("Type1", font_dict->GetNameFor("Subtype"));
2753 EXPECT_EQ("TimesNewRomanPS-BoldMT", font_dict->GetNameFor("BaseFont"));
Nicolas Penabe90aae2017-02-27 10:41:41 -05002754 ASSERT_TRUE(font_dict->KeyExist("FirstChar"));
2755 ASSERT_TRUE(font_dict->KeyExist("LastChar"));
2756 EXPECT_EQ(32, font_dict->GetIntegerFor("FirstChar"));
Nicolas Penad03ca422017-03-06 13:54:33 -05002757 EXPECT_EQ(255, font_dict->GetIntegerFor("LastChar"));
2758
Lei Zhangde579ab2018-05-25 21:49:49 +00002759 const CPDF_Array* widths_array = font_dict->GetArrayFor("Widths");
Nicolas Penad03ca422017-03-06 13:54:33 -05002760 ASSERT_TRUE(widths_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002761 ASSERT_EQ(224u, widths_array->size());
Nicolas Penabe90aae2017-02-27 10:41:41 -05002762 EXPECT_EQ(250, widths_array->GetNumberAt(0));
Nicolas Penad03ca422017-03-06 13:54:33 -05002763 EXPECT_EQ(569, widths_array->GetNumberAt(11));
2764 EXPECT_EQ(500, widths_array->GetNumberAt(223));
Tom Sepez20c41a52018-08-29 23:53:53 +00002765 CheckFontDescriptor(font_dict, FPDF_FONT_TYPE1, true, false, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05002766}
Nicolas Penabe90aae2017-02-27 10:41:41 -05002767
Lei Zhangab41f252018-12-23 03:10:50 +00002768TEST_F(FPDFEditEmbedderTest, LoadSimpleTrueTypeFont) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002769 CreateNewDocument();
Tom Sepezffff6c52019-07-30 21:56:19 +00002770 RetainPtr<CPDF_Font> stock_font =
2771 CPDF_Font::GetStockFont(cpdf_doc(), "Courier");
Tom Sepez20c41a52018-08-29 23:53:53 +00002772 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2773 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2774 FPDF_FONT_TRUETYPE, false));
Nicolas Penab3161852017-05-02 14:12:50 -04002775 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002776 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002777 EXPECT_TRUE(typed_font->IsTrueTypeFont());
Nicolas Penabe90aae2017-02-27 10:41:41 -05002778
Lei Zhang710fa992018-05-25 16:24:48 +00002779 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002780 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2781 EXPECT_EQ("TrueType", font_dict->GetNameFor("Subtype"));
2782 EXPECT_EQ("CourierNewPSMT", font_dict->GetNameFor("BaseFont"));
Nicolas Penad03ca422017-03-06 13:54:33 -05002783 ASSERT_TRUE(font_dict->KeyExist("FirstChar"));
2784 ASSERT_TRUE(font_dict->KeyExist("LastChar"));
2785 EXPECT_EQ(32, font_dict->GetIntegerFor("FirstChar"));
2786 EXPECT_EQ(255, font_dict->GetIntegerFor("LastChar"));
Nicolas Penabe90aae2017-02-27 10:41:41 -05002787
Lei Zhangde579ab2018-05-25 21:49:49 +00002788 const CPDF_Array* widths_array = font_dict->GetArrayFor("Widths");
Nicolas Penad03ca422017-03-06 13:54:33 -05002789 ASSERT_TRUE(widths_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002790 ASSERT_EQ(224u, widths_array->size());
Nicolas Penad03ca422017-03-06 13:54:33 -05002791 EXPECT_EQ(600, widths_array->GetNumberAt(33));
2792 EXPECT_EQ(600, widths_array->GetNumberAt(74));
2793 EXPECT_EQ(600, widths_array->GetNumberAt(223));
Tom Sepez20c41a52018-08-29 23:53:53 +00002794 CheckFontDescriptor(font_dict, FPDF_FONT_TRUETYPE, false, false, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05002795}
2796
Lei Zhangab41f252018-12-23 03:10:50 +00002797TEST_F(FPDFEditEmbedderTest, LoadCIDType0Font) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002798 CreateNewDocument();
Tom Sepezffff6c52019-07-30 21:56:19 +00002799 RetainPtr<CPDF_Font> stock_font =
Nicolas Penad03ca422017-03-06 13:54:33 -05002800 CPDF_Font::GetStockFont(cpdf_doc(), "Times-Roman");
Tom Sepez20c41a52018-08-29 23:53:53 +00002801 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2802 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2803 FPDF_FONT_TYPE1, 1));
Nicolas Penab3161852017-05-02 14:12:50 -04002804 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002805 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002806 EXPECT_TRUE(typed_font->IsCIDFont());
2807
2808 // Check font dictionary entries
Lei Zhang710fa992018-05-25 16:24:48 +00002809 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002810 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2811 EXPECT_EQ("Type0", font_dict->GetNameFor("Subtype"));
2812 EXPECT_EQ("TimesNewRomanPSMT-Identity-H", font_dict->GetNameFor("BaseFont"));
2813 EXPECT_EQ("Identity-H", font_dict->GetNameFor("Encoding"));
Lei Zhangde579ab2018-05-25 21:49:49 +00002814 const CPDF_Array* descendant_array =
2815 font_dict->GetArrayFor("DescendantFonts");
Nicolas Penad03ca422017-03-06 13:54:33 -05002816 ASSERT_TRUE(descendant_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002817 EXPECT_EQ(1u, descendant_array->size());
Nicolas Penad03ca422017-03-06 13:54:33 -05002818
2819 // Check the CIDFontDict
Lei Zhangde579ab2018-05-25 21:49:49 +00002820 const CPDF_Dictionary* cidfont_dict = descendant_array->GetDictAt(0);
Lei Zhanga228ff32020-06-24 17:39:33 +00002821 EXPECT_EQ("Font", cidfont_dict->GetNameFor("Type"));
2822 EXPECT_EQ("CIDFontType0", cidfont_dict->GetNameFor("Subtype"));
2823 EXPECT_EQ("TimesNewRomanPSMT", cidfont_dict->GetNameFor("BaseFont"));
Lei Zhangb1ec2802018-05-25 21:55:24 +00002824 const CPDF_Dictionary* cidinfo_dict =
2825 cidfont_dict->GetDictFor("CIDSystemInfo");
Nicolas Penad03ca422017-03-06 13:54:33 -05002826 ASSERT_TRUE(cidinfo_dict);
Lei Zhang9c950b12019-01-16 19:06:37 +00002827 const CPDF_Object* registry = cidinfo_dict->GetObjectFor("Registry");
2828 ASSERT_TRUE(registry);
KDr28da0e1b2019-01-17 03:44:29 +00002829 EXPECT_EQ(CPDF_Object::kString, registry->GetType());
Lei Zhang9c950b12019-01-16 19:06:37 +00002830 EXPECT_EQ("Adobe", registry->GetString());
2831 const CPDF_Object* ordering = cidinfo_dict->GetObjectFor("Ordering");
2832 ASSERT_TRUE(ordering);
KDr28da0e1b2019-01-17 03:44:29 +00002833 EXPECT_EQ(CPDF_Object::kString, ordering->GetType());
Lei Zhang9c950b12019-01-16 19:06:37 +00002834 EXPECT_EQ("Identity", ordering->GetString());
Nicolas Penad03ca422017-03-06 13:54:33 -05002835 EXPECT_EQ(0, cidinfo_dict->GetNumberFor("Supplement"));
Tom Sepez20c41a52018-08-29 23:53:53 +00002836 CheckFontDescriptor(cidfont_dict, FPDF_FONT_TYPE1, false, false, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05002837
2838 // Check widths
Lei Zhangde579ab2018-05-25 21:49:49 +00002839 const CPDF_Array* widths_array = cidfont_dict->GetArrayFor("W");
Nicolas Penad03ca422017-03-06 13:54:33 -05002840 ASSERT_TRUE(widths_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002841 EXPECT_GT(widths_array->size(), 1u);
Nicolas Penad03ca422017-03-06 13:54:33 -05002842 CheckCompositeFontWidths(widths_array, typed_font);
2843}
2844
Lei Zhangab41f252018-12-23 03:10:50 +00002845TEST_F(FPDFEditEmbedderTest, LoadCIDType2Font) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002846 CreateNewDocument();
Tom Sepezffff6c52019-07-30 21:56:19 +00002847 RetainPtr<CPDF_Font> stock_font =
Nicolas Penad03ca422017-03-06 13:54:33 -05002848 CPDF_Font::GetStockFont(cpdf_doc(), "Helvetica-Oblique");
Tom Sepez20c41a52018-08-29 23:53:53 +00002849 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2850 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2851 FPDF_FONT_TRUETYPE, 1));
Nicolas Penab3161852017-05-02 14:12:50 -04002852 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002853 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002854 EXPECT_TRUE(typed_font->IsCIDFont());
2855
2856 // Check font dictionary entries
Lei Zhang710fa992018-05-25 16:24:48 +00002857 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002858 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2859 EXPECT_EQ("Type0", font_dict->GetNameFor("Subtype"));
2860 EXPECT_EQ("Arial-ItalicMT", font_dict->GetNameFor("BaseFont"));
2861 EXPECT_EQ("Identity-H", font_dict->GetNameFor("Encoding"));
Lei Zhangde579ab2018-05-25 21:49:49 +00002862 const CPDF_Array* descendant_array =
2863 font_dict->GetArrayFor("DescendantFonts");
Nicolas Penad03ca422017-03-06 13:54:33 -05002864 ASSERT_TRUE(descendant_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002865 EXPECT_EQ(1u, descendant_array->size());
Nicolas Penad03ca422017-03-06 13:54:33 -05002866
2867 // Check the CIDFontDict
Lei Zhangde579ab2018-05-25 21:49:49 +00002868 const CPDF_Dictionary* cidfont_dict = descendant_array->GetDictAt(0);
Lei Zhanga228ff32020-06-24 17:39:33 +00002869 EXPECT_EQ("Font", cidfont_dict->GetNameFor("Type"));
2870 EXPECT_EQ("CIDFontType2", cidfont_dict->GetNameFor("Subtype"));
2871 EXPECT_EQ("Arial-ItalicMT", cidfont_dict->GetNameFor("BaseFont"));
Lei Zhangb1ec2802018-05-25 21:55:24 +00002872 const CPDF_Dictionary* cidinfo_dict =
2873 cidfont_dict->GetDictFor("CIDSystemInfo");
Nicolas Penad03ca422017-03-06 13:54:33 -05002874 ASSERT_TRUE(cidinfo_dict);
2875 EXPECT_EQ("Adobe", cidinfo_dict->GetStringFor("Registry"));
2876 EXPECT_EQ("Identity", cidinfo_dict->GetStringFor("Ordering"));
2877 EXPECT_EQ(0, cidinfo_dict->GetNumberFor("Supplement"));
Tom Sepez20c41a52018-08-29 23:53:53 +00002878 CheckFontDescriptor(cidfont_dict, FPDF_FONT_TRUETYPE, false, true, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05002879
2880 // Check widths
Lei Zhangde579ab2018-05-25 21:49:49 +00002881 const CPDF_Array* widths_array = cidfont_dict->GetArrayFor("W");
Nicolas Penad03ca422017-03-06 13:54:33 -05002882 ASSERT_TRUE(widths_array);
2883 CheckCompositeFontWidths(widths_array, typed_font);
Nicolas Penabe90aae2017-02-27 10:41:41 -05002884}
rbpotterce8e51e2017-04-28 12:42:47 -07002885
Lei Zhangab41f252018-12-23 03:10:50 +00002886TEST_F(FPDFEditEmbedderTest, NormalizeNegativeRotation) {
rbpotterce8e51e2017-04-28 12:42:47 -07002887 // Load document with a -90 degree rotation
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002888 ASSERT_TRUE(OpenDocument("bug_713197.pdf"));
rbpotterce8e51e2017-04-28 12:42:47 -07002889 FPDF_PAGE page = LoadPage(0);
2890 EXPECT_NE(nullptr, page);
2891
2892 EXPECT_EQ(3, FPDFPage_GetRotation(page));
2893 UnloadPage(page);
2894}
Nicolas Penab3161852017-05-02 14:12:50 -04002895
Hui Yingst9d6ec8f2020-11-05 23:35:38 +00002896TEST_F(FPDFEditEmbedderTest, AddTrueTypeFontText) {
Nicolas Penab3161852017-05-02 14:12:50 -04002897 // Start with a blank page
2898 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
2899 {
Tom Sepezffff6c52019-07-30 21:56:19 +00002900 RetainPtr<CPDF_Font> stock_font =
2901 CPDF_Font::GetStockFont(cpdf_doc(), "Arial");
Tom Sepez20c41a52018-08-29 23:53:53 +00002902 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2903 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2904 FPDF_FONT_TRUETYPE, 0));
Nicolas Penab3161852017-05-02 14:12:50 -04002905 ASSERT_TRUE(font.get());
2906
2907 // Add some text to the page
2908 FPDF_PAGEOBJECT text_object =
2909 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
2910 EXPECT_TRUE(text_object);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002911 ScopedFPDFWideString text = GetFPDFWideString(kLoadedFontText);
Nicolas Penab3161852017-05-02 14:12:50 -04002912 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2913 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 400, 400);
2914 FPDFPage_InsertObject(page, text_object);
Lei Zhang30ff2532019-01-31 21:37:55 +00002915 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002916 CompareBitmap(page_bitmap.get(), 612, 792, kLoadedFontTextChecksum);
Nicolas Penab3161852017-05-02 14:12:50 -04002917
2918 // Add some more text, same font
2919 FPDF_PAGEOBJECT text_object2 =
2920 FPDFPageObj_CreateTextObj(document(), font.get(), 15.0f);
Lei Zhangf0f67682019-04-08 17:03:21 +00002921 ScopedFPDFWideString text2 = GetFPDFWideString(L"Bigger font size");
Nicolas Penab3161852017-05-02 14:12:50 -04002922 EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
2923 FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 200, 200);
2924 FPDFPage_InsertObject(page, text_object2);
Nicolas Penab3161852017-05-02 14:12:50 -04002925 }
Lei Zhang30ff2532019-01-31 21:37:55 +00002926 ScopedFPDFBitmap page_bitmap2 = RenderPage(page);
Hui Yingst9d6ec8f2020-11-05 23:35:38 +00002927#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2928#if defined(OS_WIN)
2929 const char kInsertTrueTypeChecksum[] = "c80411cb051a9d45c4b7a8ec8a72637d";
2930#else
2931 const char kInsertTrueTypeChecksum[] = "f2ee263957a5584f3c72424e8683ac8c";
2932#endif // defined(OS_WIN)
2933#else
Hui Yingst3b6136a2020-06-09 00:39:33 +00002934#if defined(OS_WIN)
2935 const char kInsertTrueTypeChecksum[] = "2199b579c49ab5f80c246a586a80ee90";
Lei Zhang0c03d632020-07-30 17:05:36 +00002936#elif defined(OS_APPLE)
Hui Yingst3b6136a2020-06-09 00:39:33 +00002937 const char kInsertTrueTypeChecksum[] = "9a1a7dfebe659513691aadd0d95b8d50";
Nicolas Penab3161852017-05-02 14:12:50 -04002938#else
Hui Yingst3b6136a2020-06-09 00:39:33 +00002939 const char kInsertTrueTypeChecksum[] = "c1d10cce1761c4a998a16b2562030568";
Lei Zhange4cdac52019-04-30 16:45:57 +00002940#endif
Hui Yingst9d6ec8f2020-11-05 23:35:38 +00002941#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingst3b6136a2020-06-09 00:39:33 +00002942 CompareBitmap(page_bitmap2.get(), 612, 792, kInsertTrueTypeChecksum);
Nicolas Penab3161852017-05-02 14:12:50 -04002943
Nicolas Pena207b7272017-05-26 17:37:06 -04002944 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Nicolas Penab3161852017-05-02 14:12:50 -04002945 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2946 FPDF_ClosePage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04002947
Hui Yingst3b6136a2020-06-09 00:39:33 +00002948 VerifySavedDocument(612, 792, kInsertTrueTypeChecksum);
Nicolas Penab3161852017-05-02 14:12:50 -04002949}
Nicolas Penaf45ade32017-05-03 10:23:49 -04002950
Lei Zhangab41f252018-12-23 03:10:50 +00002951TEST_F(FPDFEditEmbedderTest, TransformAnnot) {
Jane Liueda65252017-06-07 11:31:27 -04002952 // Open a file with one annotation and load its first page.
2953 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00002954 FPDF_PAGE page = LoadPage(0);
Jane Liueda65252017-06-07 11:31:27 -04002955 ASSERT_TRUE(page);
2956
Lei Zhanga21d5932018-02-05 18:28:38 +00002957 {
2958 // Add an underline annotation to the page without specifying its rectangle.
Tom Sepeze08d2b12018-04-25 18:49:32 +00002959 ScopedFPDFAnnotation annot(
Lei Zhanga21d5932018-02-05 18:28:38 +00002960 FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE));
2961 ASSERT_TRUE(annot);
Jane Liueda65252017-06-07 11:31:27 -04002962
Lei Zhanga21d5932018-02-05 18:28:38 +00002963 // FPDFPage_TransformAnnots() should run without errors when modifying
2964 // annotation rectangles.
2965 FPDFPage_TransformAnnots(page, 1, 2, 3, 4, 5, 6);
2966 }
Jane Liueda65252017-06-07 11:31:27 -04002967 UnloadPage(page);
2968}
2969
Nicolas Penaf45ade32017-05-03 10:23:49 -04002970// TODO(npm): Add tests using Japanese fonts in other OS.
Lei Zhangfe8e7582020-08-05 19:23:16 +00002971#if defined(OS_LINUX) || defined(OS_CHROMEOS)
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002972TEST_F(FPDFEditEmbedderTest, AddCIDFontText) {
Nicolas Penaf45ade32017-05-03 10:23:49 -04002973 // Start with a blank page
2974 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
2975 CFX_Font CIDfont;
2976 {
2977 // First, get the data from the font
2978 CIDfont.LoadSubst("IPAGothic", 1, 0, 400, 0, 932, 0);
2979 EXPECT_EQ("IPAGothic", CIDfont.GetFaceName());
Tom Sepez20c41a52018-08-29 23:53:53 +00002980 pdfium::span<const uint8_t> span = CIDfont.GetFontSpan();
Nicolas Penaf45ade32017-05-03 10:23:49 -04002981
2982 // Load the data into a FPDF_Font.
Tom Sepez20c41a52018-08-29 23:53:53 +00002983 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2984 FPDF_FONT_TRUETYPE, 1));
Nicolas Penaf45ade32017-05-03 10:23:49 -04002985 ASSERT_TRUE(font.get());
2986
2987 // Add some text to the page
2988 FPDF_PAGEOBJECT text_object =
2989 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
2990 ASSERT_TRUE(text_object);
2991 std::wstring wstr = L"ABCDEFGhijklmnop.";
Lei Zhangf0f67682019-04-08 17:03:21 +00002992 ScopedFPDFWideString text = GetFPDFWideString(wstr);
Nicolas Penaf45ade32017-05-03 10:23:49 -04002993 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2994 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 200, 200);
2995 FPDFPage_InsertObject(page, text_object);
2996
2997 // And add some Japanese characters
2998 FPDF_PAGEOBJECT text_object2 =
2999 FPDFPageObj_CreateTextObj(document(), font.get(), 18.0f);
3000 ASSERT_TRUE(text_object2);
3001 std::wstring wstr2 =
3002 L"\u3053\u3093\u306B\u3061\u306f\u4e16\u754C\u3002\u3053\u3053\u306B1"
3003 L"\u756A";
Lei Zhangf0f67682019-04-08 17:03:21 +00003004 ScopedFPDFWideString text2 = GetFPDFWideString(wstr2);
Nicolas Penaf45ade32017-05-03 10:23:49 -04003005 EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
3006 FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 100, 500);
3007 FPDFPage_InsertObject(page, text_object2);
3008 }
3009
Nicolas Pena207b7272017-05-26 17:37:06 -04003010 // Check that the text renders properly.
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00003011#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
3012 static constexpr char md5[] = "683eefd6c31206de23b7f709b66e6daf";
3013#else
3014 static constexpr char md5[] = "5159a72903fe57bf0cf645c894de8a74";
3015#endif
Lei Zhang107fa7b2018-02-09 21:48:15 +00003016 {
Lei Zhang30ff2532019-01-31 21:37:55 +00003017 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00003018 CompareBitmap(page_bitmap.get(), 612, 792, md5);
3019 }
Nicolas Penaf45ade32017-05-03 10:23:49 -04003020
3021 // Save the document, close the page.
Nicolas Pena207b7272017-05-26 17:37:06 -04003022 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Nicolas Penaf45ade32017-05-03 10:23:49 -04003023 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3024 FPDF_ClosePage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04003025
3026 VerifySavedDocument(612, 792, md5);
Nicolas Penaf45ade32017-05-03 10:23:49 -04003027}
Lei Zhangfe8e7582020-08-05 19:23:16 +00003028#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003029
Hui Yingst29d377b2021-03-03 20:22:41 +00003030// TODO(crbug.com/pdfium/1651): Fix this issue and enable the test for Skia.
3031#if defined(_SKIA_SUPPORT_)
Lei Zhang03e5e682019-09-16 19:45:55 +00003032#define MAYBE_SaveAndRender DISABLED_SaveAndRender
3033#else
3034#define MAYBE_SaveAndRender SaveAndRender
3035#endif
3036TEST_F(FPDFEditEmbedderTest, MAYBE_SaveAndRender) {
Hui Yingst29d377b2021-03-03 20:22:41 +00003037#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
3038 static constexpr char kChecksum[] = "0e8b079e349e34f64211c495845a3529";
3039#else
3040 static constexpr char kChecksum[] = "3c20472b0552c0c22b88ab1ed8c6202b";
3041#endif
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003042 {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003043 ASSERT_TRUE(OpenDocument("bug_779.pdf"));
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003044 FPDF_PAGE page = LoadPage(0);
3045 ASSERT_NE(nullptr, page);
3046
Hui Yingst29d377b2021-03-03 20:22:41 +00003047 // Now add a more complex green path.
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003048 FPDF_PAGEOBJECT green_path = FPDFPageObj_CreateNewPath(20, 20);
Lei Zhang3475b482019-05-13 18:30:57 +00003049 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_path, 0, 255, 0, 200));
Hui Yingst29d377b2021-03-03 20:22:41 +00003050 // TODO(npm): stroking will cause the checksums to differ.
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003051 EXPECT_TRUE(FPDFPath_SetDrawMode(green_path, FPDF_FILLMODE_WINDING, 0));
3052 EXPECT_TRUE(FPDFPath_LineTo(green_path, 20, 63));
3053 EXPECT_TRUE(FPDFPath_BezierTo(green_path, 55, 55, 78, 78, 90, 90));
3054 EXPECT_TRUE(FPDFPath_LineTo(green_path, 133, 133));
3055 EXPECT_TRUE(FPDFPath_LineTo(green_path, 133, 33));
3056 EXPECT_TRUE(FPDFPath_BezierTo(green_path, 38, 33, 39, 36, 40, 40));
3057 EXPECT_TRUE(FPDFPath_Close(green_path));
3058 FPDFPage_InsertObject(page, green_path);
Tom Sepeze08d2b12018-04-25 18:49:32 +00003059 ScopedFPDFBitmap page_bitmap = RenderLoadedPage(page);
Hui Yingst29d377b2021-03-03 20:22:41 +00003060 CompareBitmap(page_bitmap.get(), 612, 792, kChecksum);
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003061
3062 // Now save the result, closing the page and document
3063 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3064 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3065 UnloadPage(page);
3066 }
Dan Sinclair04e4dc82017-10-18 12:17:14 -04003067
Hui Yingst29d377b2021-03-03 20:22:41 +00003068 VerifySavedDocument(612, 792, kChecksum);
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003069}
Jane Liu28fb7ba2017-08-02 21:45:57 -04003070
Lei Zhangab41f252018-12-23 03:10:50 +00003071TEST_F(FPDFEditEmbedderTest, AddMark) {
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003072 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003073 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003074 FPDF_PAGE page = LoadPage(0);
3075 ASSERT_TRUE(page);
3076
Lei Zhang2697cb12019-07-03 18:14:29 +00003077 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003078
3079 // Add to the first page object a "Bounds" mark with "Position": "First".
3080 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
3081 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_AddMark(page_object, "Bounds");
3082 EXPECT_TRUE(mark);
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003083 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), page_object, mark,
3084 "Position", "First"));
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003085
Lei Zhang2697cb12019-07-03 18:14:29 +00003086 CheckMarkCounts(page, 1, 19, 8, 4, 9, 2);
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003087
3088 // Save the file
3089 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3090 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3091 UnloadPage(page);
3092
3093 // Re-open the file and check the new mark is present.
Lei Zhang0b494052019-01-31 21:41:15 +00003094 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003095 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00003096 ASSERT_TRUE(saved_page);
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003097
Lei Zhang2697cb12019-07-03 18:14:29 +00003098 CheckMarkCounts(saved_page, 1, 19, 8, 4, 9, 2);
3099
3100 CloseSavedPage(saved_page);
3101 CloseSavedDocument();
3102}
3103
Hui Yingst04440af2020-07-27 22:39:02 +00003104TEST_F(FPDFEditEmbedderTest, AddMarkCompressedStream) {
Lei Zhang2697cb12019-07-03 18:14:29 +00003105 // Load document with some text in a compressed stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003106 ASSERT_TRUE(OpenDocument("hello_world_compressed_stream.pdf"));
Lei Zhang2697cb12019-07-03 18:14:29 +00003107 FPDF_PAGE page = LoadPage(0);
3108 ASSERT_TRUE(page);
3109
3110 // Render and check there are no marks.
3111 {
3112 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00003113 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Lei Zhang2697cb12019-07-03 18:14:29 +00003114 }
3115 CheckMarkCounts(page, 0, 2, 0, 0, 0, 0);
3116
3117 // Add to the first page object a "Bounds" mark with "Position": "First".
3118 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
3119 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_AddMark(page_object, "Bounds");
3120 EXPECT_TRUE(mark);
3121 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), page_object, mark,
3122 "Position", "First"));
3123
3124 // Render and check there is 1 mark.
3125 {
3126 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00003127 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Lei Zhang2697cb12019-07-03 18:14:29 +00003128 }
3129 CheckMarkCounts(page, 0, 2, 0, 0, 0, 1);
3130
3131 // Save the file.
3132 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3133 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3134 UnloadPage(page);
3135
3136 // Re-open the file and check the new mark is present.
3137 ASSERT_TRUE(OpenSavedDocument());
3138 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00003139 ASSERT_TRUE(saved_page);
Lei Zhang2697cb12019-07-03 18:14:29 +00003140
3141 {
3142 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00003143 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Lei Zhang2697cb12019-07-03 18:14:29 +00003144 }
3145 CheckMarkCounts(saved_page, 0, 2, 0, 0, 0, 1);
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003146
3147 CloseSavedPage(saved_page);
3148 CloseSavedDocument();
3149}
3150
Lei Zhangab41f252018-12-23 03:10:50 +00003151TEST_F(FPDFEditEmbedderTest, SetMarkParam) {
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003152 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003153 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003154 FPDF_PAGE page = LoadPage(0);
3155 ASSERT_TRUE(page);
3156
3157 constexpr int kExpectedObjectCount = 19;
3158 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
3159
3160 // Check the "Bounds" mark's "Position" param is "Last".
3161 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
3162 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
3163 ASSERT_TRUE(mark);
3164 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003165 unsigned long name_len = 999u;
3166 ASSERT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
3167 EXPECT_EQ((6u + 1u) * 2u, name_len);
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003168 ASSERT_EQ(L"Bounds",
3169 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3170 unsigned long out_buffer_len;
3171 ASSERT_TRUE(FPDFPageObjMark_GetParamStringValue(
3172 mark, "Position", buffer, sizeof(buffer), &out_buffer_len));
3173 ASSERT_EQ(L"Last",
3174 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3175
3176 // Set is to "End".
3177 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), page_object, mark,
3178 "Position", "End"));
3179
3180 // Verify the object passed must correspond to the mark passed.
3181 FPDF_PAGEOBJECT another_page_object = FPDFPage_GetObject(page, 17);
3182 EXPECT_FALSE(FPDFPageObjMark_SetStringParam(document(), another_page_object,
3183 mark, "Position", "End"));
3184
3185 // Verify nothing else changed.
3186 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
3187
3188 // Verify "Position" now maps to "End".
3189 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
3190 mark, "Position", buffer, sizeof(buffer), &out_buffer_len));
3191 EXPECT_EQ(L"End",
3192 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3193
3194 // Save the file
3195 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3196 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3197 UnloadPage(page);
3198
3199 // Re-open the file and cerify "Position" still maps to "End".
Lei Zhang0b494052019-01-31 21:41:15 +00003200 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003201 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00003202 ASSERT_TRUE(saved_page);
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003203
3204 CheckMarkCounts(saved_page, 1, kExpectedObjectCount, 8, 4, 9, 1);
3205 page_object = FPDFPage_GetObject(saved_page, 18);
3206 mark = FPDFPageObj_GetMark(page_object, 1);
3207 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
3208 mark, "Position", buffer, sizeof(buffer), &out_buffer_len));
3209 EXPECT_EQ(L"End",
3210 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3211
3212 CloseSavedPage(saved_page);
3213 CloseSavedDocument();
3214}
3215
Hui Yingst9d6ec8f2020-11-05 23:35:38 +00003216TEST_F(FPDFEditEmbedderTest, AddMarkedText) {
Henrique Nakashima144107d2018-07-10 21:04:05 +00003217 // Start with a blank page.
3218 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
3219
Tom Sepezffff6c52019-07-30 21:56:19 +00003220 RetainPtr<CPDF_Font> stock_font =
3221 CPDF_Font::GetStockFont(cpdf_doc(), "Arial");
Tom Sepez20c41a52018-08-29 23:53:53 +00003222 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
3223 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
3224 FPDF_FONT_TRUETYPE, 0));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003225 ASSERT_TRUE(font.get());
3226
3227 // Add some text to the page.
3228 FPDF_PAGEOBJECT text_object =
3229 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
3230
3231 EXPECT_TRUE(text_object);
Hui Yingst3b6136a2020-06-09 00:39:33 +00003232 ScopedFPDFWideString text1 = GetFPDFWideString(kLoadedFontText);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003233 EXPECT_TRUE(FPDFText_SetText(text_object, text1.get()));
3234 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 400, 400);
3235 FPDFPage_InsertObject(page, text_object);
3236
3237 // Add a mark with the tag "TestMarkName" to that text.
3238 EXPECT_EQ(0, FPDFPageObj_CountMarks(text_object));
Henrique Nakashima6fc8d872018-09-18 16:48:31 +00003239 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_AddMark(text_object, "Test Mark Name");
Henrique Nakashima144107d2018-07-10 21:04:05 +00003240 EXPECT_TRUE(mark);
3241 EXPECT_EQ(1, FPDFPageObj_CountMarks(text_object));
3242 EXPECT_EQ(mark, FPDFPageObj_GetMark(text_object, 0));
3243 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003244 unsigned long name_len = 999u;
3245 ASSERT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
3246 EXPECT_EQ((14u + 1u) * 2, name_len);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003247 std::wstring name =
3248 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
Henrique Nakashima6fc8d872018-09-18 16:48:31 +00003249 EXPECT_EQ(L"Test Mark Name", name);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003250
3251 // Add parameters:
3252 // - int "IntKey" : 42
3253 // - string "StringKey": "StringValue"
Henrique Nakashima07520f62018-07-12 19:45:29 +00003254 // - blob "BlobKey": "\x01\x02\x03\0BlobValue1\0\0\0BlobValue2\0"
Lei Zhang590f4242019-05-15 20:57:26 +00003255 constexpr size_t kBlobLen = 28;
Lei Zhangd3b028b2018-11-30 22:22:00 +00003256 char block_value[kBlobLen];
3257 memcpy(block_value, "\x01\x02\x03\0BlobValue1\0\0\0BlobValue2\0", kBlobLen);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003258 EXPECT_EQ(0, FPDFPageObjMark_CountParams(mark));
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003259 EXPECT_TRUE(
3260 FPDFPageObjMark_SetIntParam(document(), text_object, mark, "IntKey", 42));
3261 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), text_object, mark,
3262 "StringKey", "StringValue"));
3263 EXPECT_TRUE(FPDFPageObjMark_SetBlobParam(document(), text_object, mark,
Lei Zhangd3b028b2018-11-30 22:22:00 +00003264 "BlobKey", block_value, kBlobLen));
Henrique Nakashima07520f62018-07-12 19:45:29 +00003265 EXPECT_EQ(3, FPDFPageObjMark_CountParams(mark));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003266
3267 // Check the two parameters can be retrieved.
3268 EXPECT_EQ(FPDF_OBJECT_NUMBER,
Henrique Nakashima94230e52018-07-11 22:02:02 +00003269 FPDFPageObjMark_GetParamValueType(mark, "IntKey"));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003270 int int_value;
Henrique Nakashima94230e52018-07-11 22:02:02 +00003271 EXPECT_TRUE(FPDFPageObjMark_GetParamIntValue(mark, "IntKey", &int_value));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003272 EXPECT_EQ(42, int_value);
3273
3274 EXPECT_EQ(FPDF_OBJECT_STRING,
Henrique Nakashima94230e52018-07-11 22:02:02 +00003275 FPDFPageObjMark_GetParamValueType(mark, "StringKey"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003276 unsigned long out_buffer_len = 999u;
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003277 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
3278 mark, "StringKey", buffer, sizeof(buffer), &out_buffer_len));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003279 EXPECT_GT(out_buffer_len, 0u);
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003280 EXPECT_NE(999u, out_buffer_len);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003281 name = GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
3282 EXPECT_EQ(L"StringValue", name);
3283
Henrique Nakashima07520f62018-07-12 19:45:29 +00003284 EXPECT_EQ(FPDF_OBJECT_STRING,
3285 FPDFPageObjMark_GetParamValueType(mark, "BlobKey"));
3286 out_buffer_len = 0;
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003287 EXPECT_TRUE(FPDFPageObjMark_GetParamBlobValue(
3288 mark, "BlobKey", buffer, sizeof(buffer), &out_buffer_len));
Henrique Nakashima07520f62018-07-12 19:45:29 +00003289 EXPECT_EQ(kBlobLen, out_buffer_len);
Lei Zhangd3b028b2018-11-30 22:22:00 +00003290 EXPECT_EQ(0, memcmp(block_value, buffer, kBlobLen));
Henrique Nakashima07520f62018-07-12 19:45:29 +00003291
Lei Zhangf16376e2020-06-18 19:19:32 +00003292 // Render and check the bitmap is the expected one.
Henrique Nakashima144107d2018-07-10 21:04:05 +00003293 {
Lei Zhang30ff2532019-01-31 21:37:55 +00003294 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00003295 CompareBitmap(page_bitmap.get(), 612, 792, kLoadedFontTextChecksum);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003296 }
3297
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003298 // Now save the result.
3299 EXPECT_EQ(1, FPDFPage_CountObjects(page));
3300 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3301 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3302
Henrique Nakashima144107d2018-07-10 21:04:05 +00003303 FPDF_ClosePage(page);
3304
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003305 // Re-open the file and check the changes were kept in the saved .pdf.
Lei Zhang0b494052019-01-31 21:41:15 +00003306 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003307 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00003308 ASSERT_TRUE(saved_page);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003309 EXPECT_EQ(1, FPDFPage_CountObjects(saved_page));
3310
3311 text_object = FPDFPage_GetObject(saved_page, 0);
3312 EXPECT_TRUE(text_object);
3313 EXPECT_EQ(1, FPDFPageObj_CountMarks(text_object));
3314 mark = FPDFPageObj_GetMark(text_object, 0);
3315 EXPECT_TRUE(mark);
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003316
3317 name_len = 999u;
3318 ASSERT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
3319 EXPECT_EQ((14u + 1u) * 2, name_len);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003320 name = GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
Henrique Nakashima6fc8d872018-09-18 16:48:31 +00003321 EXPECT_EQ(L"Test Mark Name", name);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003322
3323 CloseSavedPage(saved_page);
3324 CloseSavedDocument();
Henrique Nakashima144107d2018-07-10 21:04:05 +00003325}
3326
Lei Zhangab41f252018-12-23 03:10:50 +00003327TEST_F(FPDFEditEmbedderTest, MarkGetName) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003328 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003329 FPDF_PAGE page = LoadPage(0);
3330 ASSERT_TRUE(page);
3331 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
3332 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
3333 ASSERT_TRUE(mark);
3334
3335 char buffer[256];
3336 unsigned long out_len;
3337
3338 // Show the positive cases of FPDFPageObjMark_GetName.
3339 out_len = 999u;
3340 EXPECT_TRUE(FPDFPageObjMark_GetName(mark, nullptr, 0, &out_len));
3341 EXPECT_EQ((6u + 1u) * 2u, out_len);
3342
3343 out_len = 999u;
3344 EXPECT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &out_len));
3345 EXPECT_EQ(L"Bounds",
3346 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3347 EXPECT_EQ((6u + 1u) * 2u, out_len);
3348
3349 // Show the negative cases of FPDFPageObjMark_GetName.
3350 out_len = 999u;
3351 EXPECT_FALSE(
3352 FPDFPageObjMark_GetName(nullptr, buffer, sizeof(buffer), &out_len));
3353 EXPECT_EQ(999u, out_len);
3354
3355 EXPECT_FALSE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), nullptr));
3356
3357 UnloadPage(page);
3358}
3359
Lei Zhangab41f252018-12-23 03:10:50 +00003360TEST_F(FPDFEditEmbedderTest, MarkGetParamKey) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003361 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003362 FPDF_PAGE page = LoadPage(0);
3363 ASSERT_TRUE(page);
3364 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
3365 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
3366 ASSERT_TRUE(mark);
3367
3368 char buffer[256];
3369 unsigned long out_len;
3370
3371 // Show the positive cases of FPDFPageObjMark_GetParamKey.
3372 out_len = 999u;
3373 EXPECT_TRUE(FPDFPageObjMark_GetParamKey(mark, 0, nullptr, 0, &out_len));
3374 EXPECT_EQ((8u + 1u) * 2u, out_len);
3375
3376 out_len = 999u;
3377 EXPECT_TRUE(
3378 FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer), &out_len));
3379 EXPECT_EQ(L"Position",
3380 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3381 EXPECT_EQ((8u + 1u) * 2u, out_len);
3382
3383 // Show the negative cases of FPDFPageObjMark_GetParamKey.
3384 out_len = 999u;
3385 EXPECT_FALSE(FPDFPageObjMark_GetParamKey(nullptr, 0, buffer, sizeof(buffer),
3386 &out_len));
3387 EXPECT_EQ(999u, out_len);
3388
3389 out_len = 999u;
3390 EXPECT_FALSE(
3391 FPDFPageObjMark_GetParamKey(mark, 1, buffer, sizeof(buffer), &out_len));
3392 EXPECT_EQ(999u, out_len);
3393
3394 EXPECT_FALSE(
3395 FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer), nullptr));
3396
3397 UnloadPage(page);
3398}
3399
Lei Zhangab41f252018-12-23 03:10:50 +00003400TEST_F(FPDFEditEmbedderTest, MarkGetIntParam) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003401 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003402 FPDF_PAGE page = LoadPage(0);
3403 ASSERT_TRUE(page);
3404 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 8);
3405 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 0);
3406 ASSERT_TRUE(mark);
3407
3408 int out_value;
3409
3410 // Show the positive cases of FPDFPageObjMark_GetParamIntValue.
3411 out_value = 999;
3412 EXPECT_TRUE(FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
3413 EXPECT_EQ(3, out_value);
3414
3415 // Show the negative cases of FPDFPageObjMark_GetParamIntValue.
3416 out_value = 999;
3417 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(nullptr, "Factor", &out_value));
3418 EXPECT_EQ(999, out_value);
3419
3420 out_value = 999;
3421 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(mark, "ParamThatDoesNotExist",
3422 &out_value));
3423 EXPECT_EQ(999, out_value);
3424
3425 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(mark, "Factor", nullptr));
3426
3427 page_object = FPDFPage_GetObject(page, 18);
3428 mark = FPDFPageObj_GetMark(page_object, 1);
3429 out_value = 999;
3430 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(mark, "Position", &out_value));
3431 EXPECT_EQ(999, out_value);
3432
3433 UnloadPage(page);
3434}
3435
Lei Zhangab41f252018-12-23 03:10:50 +00003436TEST_F(FPDFEditEmbedderTest, MarkGetStringParam) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003437 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003438 FPDF_PAGE page = LoadPage(0);
3439 ASSERT_TRUE(page);
3440 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
3441 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
3442 ASSERT_TRUE(mark);
3443
3444 char buffer[256];
3445 unsigned long out_len;
3446
3447 // Show the positive cases of FPDFPageObjMark_GetParamStringValue.
3448 out_len = 999u;
3449 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(mark, "Position", nullptr, 0,
3450 &out_len));
3451 EXPECT_EQ((4u + 1u) * 2u, out_len);
3452
3453 out_len = 999u;
3454 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(mark, "Position", buffer,
3455 sizeof(buffer), &out_len));
3456 EXPECT_EQ(L"Last",
3457 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3458 EXPECT_EQ((4u + 1u) * 2u, out_len);
3459
3460 // Show the negative cases of FPDFPageObjMark_GetParamStringValue.
3461 out_len = 999u;
3462 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(nullptr, "Position", buffer,
3463 sizeof(buffer), &out_len));
3464 EXPECT_EQ(999u, out_len);
3465
3466 out_len = 999u;
3467 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(
3468 mark, "ParamThatDoesNotExist", buffer, sizeof(buffer), &out_len));
3469 EXPECT_EQ(999u, out_len);
3470
3471 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(mark, "Position", buffer,
3472 sizeof(buffer), nullptr));
3473
3474 page_object = FPDFPage_GetObject(page, 8);
3475 mark = FPDFPageObj_GetMark(page_object, 0);
3476 out_len = 999u;
3477 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(mark, "Factor", buffer,
3478 sizeof(buffer), &out_len));
3479 EXPECT_EQ(999u, out_len);
3480
3481 UnloadPage(page);
3482}
3483
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003484TEST_F(FPDFEditEmbedderTest, GetBitmap) {
Jane Liu28fb7ba2017-08-02 21:45:57 -04003485 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3486 FPDF_PAGE page = LoadPage(0);
3487 ASSERT_TRUE(page);
Miklos Vajna92627612017-09-25 12:59:29 +02003488 ASSERT_EQ(39, FPDFPage_CountObjects(page));
Jane Liu28fb7ba2017-08-02 21:45:57 -04003489
3490 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 32);
3491 EXPECT_NE(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3492 EXPECT_FALSE(FPDFImageObj_GetBitmap(obj));
3493
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003494 {
3495 obj = FPDFPage_GetObject(page, 33);
3496 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3497 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3498 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
Lei Zhang85166512020-07-14 23:28:56 +00003499 CompareBitmap(bitmap.get(), 109, 88, kEmbeddedImage33Checksum);
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003500 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003501
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003502 {
3503 obj = FPDFPage_GetObject(page, 34);
3504 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3505 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3506 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3507 CompareBitmap(bitmap.get(), 103, 75, "c8d51fa6821ceb2a67f08446ff236c40");
3508 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003509
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003510 {
3511 obj = FPDFPage_GetObject(page, 35);
3512 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3513 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3514 EXPECT_EQ(FPDFBitmap_Gray, FPDFBitmap_GetFormat(bitmap.get()));
3515 CompareBitmap(bitmap.get(), 92, 68, "9c6d76cb1e37ef8514f9455d759391f3");
3516 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003517
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003518 {
3519 obj = FPDFPage_GetObject(page, 36);
3520 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3521 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3522 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3523 CompareBitmap(bitmap.get(), 79, 60, "f4e72fb783a01c7b4614cdc25eaa98ac");
3524 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003525
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003526 {
3527 obj = FPDFPage_GetObject(page, 37);
3528 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3529 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3530 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3531 CompareBitmap(bitmap.get(), 126, 106, "2cf9e66414c72461f4ccbf9cdebdfa1b");
3532 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003533
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003534 {
3535 obj = FPDFPage_GetObject(page, 38);
3536 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3537 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3538 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3539 CompareBitmap(bitmap.get(), 194, 119, "a8f3a126cec274dab8242fd2ccdc1b8b");
3540 }
3541
Jane Liu28fb7ba2017-08-02 21:45:57 -04003542 UnloadPage(page);
3543}
Jane Liu548334e2017-08-03 16:33:40 -04003544
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003545TEST_F(FPDFEditEmbedderTest, GetBitmapIgnoresSetMatrix) {
Lei Zhang85166512020-07-14 23:28:56 +00003546 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3547 FPDF_PAGE page = LoadPage(0);
3548 ASSERT_TRUE(page);
3549 ASSERT_EQ(39, FPDFPage_CountObjects(page));
3550
3551 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3552 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3553
3554 {
3555 // Render |obj| as is.
3556 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3557 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3558 CompareBitmap(bitmap.get(), 109, 88, kEmbeddedImage33Checksum);
3559 }
3560
3561 // Check the matrix for |obj|.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003562 FS_MATRIX matrix;
3563 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3564 EXPECT_FLOAT_EQ(53.0f, matrix.a);
3565 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3566 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3567 EXPECT_FLOAT_EQ(43.0f, matrix.d);
3568 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3569 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang85166512020-07-14 23:28:56 +00003570
3571 // Modify the matrix for |obj|.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003572 matrix.a = 120.0;
3573 EXPECT_TRUE(FPDFPageObj_SetMatrix(obj, &matrix));
Lei Zhang85166512020-07-14 23:28:56 +00003574
3575 // Make sure the matrix modification took place.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003576 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3577 EXPECT_FLOAT_EQ(120.0f, matrix.a);
3578 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3579 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3580 EXPECT_FLOAT_EQ(43.0f, matrix.d);
3581 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3582 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang85166512020-07-14 23:28:56 +00003583
3584 {
Lei Zhangc8601bf2021-06-29 23:19:27 +00003585 // Render |obj| again. Note that the FPDFPageObj_SetMatrix() call has no
Lei Zhang85166512020-07-14 23:28:56 +00003586 // effect.
3587 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3588 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3589 CompareBitmap(bitmap.get(), 109, 88, kEmbeddedImage33Checksum);
3590 }
3591
3592 UnloadPage(page);
3593}
3594
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003595TEST_F(FPDFEditEmbedderTest, GetBitmapForJBigImage) {
Lei Zhang53341dd2018-03-01 15:42:47 +00003596 ASSERT_TRUE(OpenDocument("bug_631912.pdf"));
3597 FPDF_PAGE page = LoadPage(0);
3598 ASSERT_TRUE(page);
3599 ASSERT_EQ(1, FPDFPage_CountObjects(page));
3600
3601 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
3602 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3603 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00003604 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
Lei Zhang1330ebb2018-03-05 15:16:37 +00003605 ASSERT_TRUE(bitmap);
3606 EXPECT_EQ(FPDFBitmap_Gray, FPDFBitmap_GetFormat(bitmap.get()));
3607 CompareBitmap(bitmap.get(), 1152, 720, "3f6a48e2b3e91b799bf34567f55cb4de");
Lei Zhang53341dd2018-03-01 15:42:47 +00003608 }
3609
3610 UnloadPage(page);
3611}
3612
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003613TEST_F(FPDFEditEmbedderTest, GetBitmapIgnoresSMask) {
Lei Zhang2e1b4f22020-07-08 23:40:18 +00003614 ASSERT_TRUE(OpenDocument("matte.pdf"));
3615 FPDF_PAGE page = LoadPage(0);
3616 ASSERT_TRUE(page);
3617
3618 constexpr int kExpectedObjects = 4;
3619 ASSERT_EQ(kExpectedObjects, FPDFPage_CountObjects(page));
3620
3621 for (int i = 0; i < kExpectedObjects; ++i) {
3622 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, i);
3623 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3624 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3625 ASSERT_TRUE(bitmap);
3626 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3627 CompareBitmap(bitmap.get(), 50, 50, "46c9a1dbe0b44765ce46017ad629a2fe");
3628 }
3629
3630 UnloadPage(page);
3631}
3632
Hui Yingst822fb8d2020-10-05 22:10:35 +00003633// TODO(crbug.com/pdfium/11): Fix this test and enable.
3634#if defined(_SKIA_SUPPORT_)
3635#define MAYBE_GetRenderedBitmapHandlesSetMatrix \
3636 DISABLED_GetRenderedBitmapHandlesSetMatrix
3637#else
3638#define MAYBE_GetRenderedBitmapHandlesSetMatrix \
3639 GetRenderedBitmapHandlesSetMatrix
3640#endif
3641TEST_F(FPDFEditEmbedderTest, MAYBE_GetRenderedBitmapHandlesSetMatrix) {
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003642 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3643 FPDF_PAGE page = LoadPage(0);
3644 ASSERT_TRUE(page);
3645 ASSERT_EQ(39, FPDFPage_CountObjects(page));
3646
3647 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3648 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3649
3650 {
3651 // Render |obj| as is.
3652 ScopedFPDFBitmap bitmap(
3653 FPDFImageObj_GetRenderedBitmap(document(), page, obj));
3654 EXPECT_EQ(FPDFBitmap_BGRA, FPDFBitmap_GetFormat(bitmap.get()));
Tom Sepezd661dc72021-06-24 20:22:19 +00003655 CompareBitmap(bitmap.get(), 53, 43, "582ca300e003f512d7b552c7b5b45d2e");
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003656 }
3657
3658 // Check the matrix for |obj|.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003659 FS_MATRIX matrix;
3660 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3661 EXPECT_FLOAT_EQ(53.0f, matrix.a);
3662 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3663 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3664 EXPECT_FLOAT_EQ(43.0f, matrix.d);
3665 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3666 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003667
3668 // Modify the matrix for |obj|.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003669 matrix.a = 120.0;
3670 EXPECT_TRUE(FPDFPageObj_SetMatrix(obj, &matrix));
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003671
3672 // Make sure the matrix modification took place.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003673 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3674 EXPECT_FLOAT_EQ(120.0f, matrix.a);
3675 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3676 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3677 EXPECT_FLOAT_EQ(43.0f, matrix.d);
3678 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3679 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003680
3681 {
Lei Zhangc8601bf2021-06-29 23:19:27 +00003682 // Render |obj| again. Note that the FPDFPageObj_SetMatrix() call has an
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003683 // effect.
3684 ScopedFPDFBitmap bitmap(
3685 FPDFImageObj_GetRenderedBitmap(document(), page, obj));
3686 EXPECT_EQ(FPDFBitmap_BGRA, FPDFBitmap_GetFormat(bitmap.get()));
Tom Sepezd661dc72021-06-24 20:22:19 +00003687 CompareBitmap(bitmap.get(), 120, 43, "0824c16dcf2dfcef44b45d88db1fddce");
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003688 }
3689
3690 UnloadPage(page);
3691}
3692
Hui Yingst822fb8d2020-10-05 22:10:35 +00003693// TODO(crbug.com/pdfium/11): Fix this test and enable.
3694#if defined(_SKIA_SUPPORT_)
3695#define MAYBE_GetRenderedBitmapHandlesSMask \
3696 DISABLED_GetRenderedBitmapHandlesSMask
3697#else
3698#define MAYBE_GetRenderedBitmapHandlesSMask GetRenderedBitmapHandlesSMask
3699#endif
3700TEST_F(FPDFEditEmbedderTest, MAYBE_GetRenderedBitmapHandlesSMask) {
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003701 ASSERT_TRUE(OpenDocument("matte.pdf"));
3702 FPDF_PAGE page = LoadPage(0);
3703 ASSERT_TRUE(page);
3704
3705 constexpr int kExpectedObjects = 4;
3706 ASSERT_EQ(kExpectedObjects, FPDFPage_CountObjects(page));
3707
3708 for (int i = 0; i < kExpectedObjects; ++i) {
3709 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, i);
3710 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3711 ScopedFPDFBitmap bitmap(
3712 FPDFImageObj_GetRenderedBitmap(document(), page, obj));
3713 ASSERT_TRUE(bitmap);
3714 EXPECT_EQ(FPDFBitmap_BGRA, FPDFBitmap_GetFormat(bitmap.get()));
3715 if (i == 0)
3716 CompareBitmap(bitmap.get(), 40, 60, "5a3ae4a660ce919e29c42ec2258142f1");
3717 else
3718 CompareBitmap(bitmap.get(), 40, 60, "67504e83f5d78214ea00efc19082c5c1");
3719 }
3720
3721 UnloadPage(page);
3722}
3723
3724TEST_F(FPDFEditEmbedderTest, GetRenderedBitmapBadParams) {
3725 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3726 FPDF_PAGE page = LoadPage(0);
3727 ASSERT_TRUE(page);
3728
3729 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3730 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3731
3732 // Test various null parameters.
3733 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, nullptr, nullptr));
3734 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(document(), nullptr, nullptr));
3735 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, page, nullptr));
3736 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, nullptr, obj));
3737 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(document(), page, nullptr));
3738 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, page, obj));
3739
3740 // Test mismatch between document and page parameters.
3741 ScopedFPDFDocument new_document(FPDF_CreateNewDocument());
3742 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(new_document.get(), page, obj));
3743
3744 UnloadPage(page);
3745}
3746
Lei Zhangab41f252018-12-23 03:10:50 +00003747TEST_F(FPDFEditEmbedderTest, GetImageData) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003748 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
Jane Liu548334e2017-08-03 16:33:40 -04003749 FPDF_PAGE page = LoadPage(0);
3750 ASSERT_TRUE(page);
Miklos Vajna92627612017-09-25 12:59:29 +02003751 ASSERT_EQ(39, FPDFPage_CountObjects(page));
Jane Liu548334e2017-08-03 16:33:40 -04003752
3753 // Retrieve an image object with flate-encoded data stream.
3754 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3755 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3756
3757 // Check that the raw image data has the correct length and hash value.
3758 unsigned long len = FPDFImageObj_GetImageDataRaw(obj, nullptr, 0);
3759 std::vector<char> buf(len);
3760 EXPECT_EQ(4091u, FPDFImageObj_GetImageDataRaw(obj, buf.data(), len));
3761 EXPECT_EQ("f73802327d2e88e890f653961bcda81a",
3762 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3763
3764 // Check that the decoded image data has the correct length and hash value.
3765 len = FPDFImageObj_GetImageDataDecoded(obj, nullptr, 0);
3766 buf.clear();
3767 buf.resize(len);
3768 EXPECT_EQ(28776u, FPDFImageObj_GetImageDataDecoded(obj, buf.data(), len));
Lei Zhang85166512020-07-14 23:28:56 +00003769 EXPECT_EQ(kEmbeddedImage33Checksum,
Jane Liu548334e2017-08-03 16:33:40 -04003770 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3771
Lei Zhang351e8b02018-12-20 01:10:06 +00003772 // Retrieve an image object with DCTDecode-encoded data stream.
Jane Liu548334e2017-08-03 16:33:40 -04003773 obj = FPDFPage_GetObject(page, 37);
3774 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3775
3776 // Check that the raw image data has the correct length and hash value.
3777 len = FPDFImageObj_GetImageDataRaw(obj, nullptr, 0);
3778 buf.clear();
3779 buf.resize(len);
3780 EXPECT_EQ(4370u, FPDFImageObj_GetImageDataRaw(obj, buf.data(), len));
3781 EXPECT_EQ("6aae1f3710335023a9e12191be66b64b",
3782 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3783
3784 // Check that the decoded image data has the correct length and hash value,
3785 // which should be the same as those of the raw data, since this image is
3786 // encoded by a single DCTDecode filter and decoding is a noop.
3787 len = FPDFImageObj_GetImageDataDecoded(obj, nullptr, 0);
3788 buf.clear();
3789 buf.resize(len);
3790 EXPECT_EQ(4370u, FPDFImageObj_GetImageDataDecoded(obj, buf.data(), len));
3791 EXPECT_EQ("6aae1f3710335023a9e12191be66b64b",
3792 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3793
3794 UnloadPage(page);
3795}
Jane Liu2e5f0ae2017-08-08 15:23:27 -04003796
Lei Zhangab41f252018-12-23 03:10:50 +00003797TEST_F(FPDFEditEmbedderTest, GetImageMatrix) {
Lei Zhang866d6882018-10-24 17:31:01 +00003798 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3799 FPDF_PAGE page = LoadPage(0);
3800 ASSERT_TRUE(page);
3801 ASSERT_EQ(39, FPDFPage_CountObjects(page));
3802
3803 FPDF_PAGEOBJECT obj;
Lei Zhangc8601bf2021-06-29 23:19:27 +00003804 FS_MATRIX matrix;
Lei Zhang866d6882018-10-24 17:31:01 +00003805
3806 obj = FPDFPage_GetObject(page, 33);
3807 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003808 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3809 EXPECT_FLOAT_EQ(53.0f, matrix.a);
3810 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3811 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3812 EXPECT_FLOAT_EQ(43.0f, matrix.d);
3813 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3814 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003815
3816 obj = FPDFPage_GetObject(page, 34);
3817 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003818 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3819 EXPECT_FLOAT_EQ(70.0f, matrix.a);
3820 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3821 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3822 EXPECT_FLOAT_EQ(51.0f, matrix.d);
3823 EXPECT_FLOAT_EQ(216.0f, matrix.e);
3824 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003825
3826 obj = FPDFPage_GetObject(page, 35);
3827 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003828 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3829 EXPECT_FLOAT_EQ(69.0f, matrix.a);
3830 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3831 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3832 EXPECT_FLOAT_EQ(51.0f, matrix.d);
3833 EXPECT_FLOAT_EQ(360.0f, matrix.e);
3834 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003835
3836 obj = FPDFPage_GetObject(page, 36);
3837 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003838 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3839 EXPECT_FLOAT_EQ(59.0f, matrix.a);
3840 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3841 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3842 EXPECT_FLOAT_EQ(45.0f, matrix.d);
3843 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3844 EXPECT_FLOAT_EQ(553.510009765625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003845
3846 obj = FPDFPage_GetObject(page, 37);
3847 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003848 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3849 EXPECT_FLOAT_EQ(55.94000244140625f, matrix.a);
3850 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3851 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3852 EXPECT_FLOAT_EQ(46.950000762939453f, matrix.d);
3853 EXPECT_FLOAT_EQ(216.0f, matrix.e);
3854 EXPECT_FLOAT_EQ(552.510009765625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003855
3856 obj = FPDFPage_GetObject(page, 38);
3857 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003858 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3859 EXPECT_FLOAT_EQ(70.528999328613281f, matrix.a);
3860 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3861 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3862 EXPECT_FLOAT_EQ(43.149997711181641f, matrix.d);
3863 EXPECT_FLOAT_EQ(360.0f, matrix.e);
3864 EXPECT_FLOAT_EQ(553.3599853515625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003865
3866 UnloadPage(page);
3867}
3868
Lei Zhangab41f252018-12-23 03:10:50 +00003869TEST_F(FPDFEditEmbedderTest, DestroyPageObject) {
Jane Liu2e5f0ae2017-08-08 15:23:27 -04003870 FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
3871 ASSERT_TRUE(rect);
3872
3873 // There should be no memory leaks with a call to FPDFPageObj_Destroy().
3874 FPDFPageObj_Destroy(rect);
3875}
Jane Liube63ab92017-08-09 14:09:34 -04003876
Lei Zhangab41f252018-12-23 03:10:50 +00003877TEST_F(FPDFEditEmbedderTest, GetImageFilters) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003878 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
Jane Liube63ab92017-08-09 14:09:34 -04003879 FPDF_PAGE page = LoadPage(0);
3880 ASSERT_TRUE(page);
3881
3882 // Verify that retrieving the filter of a non-image object would fail.
3883 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 32);
3884 ASSERT_NE(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3885 ASSERT_EQ(0, FPDFImageObj_GetImageFilterCount(obj));
3886 EXPECT_EQ(0u, FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0));
3887
3888 // Verify the returned filter string for an image object with a single filter.
3889 obj = FPDFPage_GetObject(page, 33);
3890 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3891 ASSERT_EQ(1, FPDFImageObj_GetImageFilterCount(obj));
3892 unsigned long len = FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0);
3893 std::vector<char> buf(len);
Lei Zhang0733a1b2017-08-31 12:36:31 -07003894 static constexpr char kFlateDecode[] = "FlateDecode";
3895 EXPECT_EQ(sizeof(kFlateDecode),
3896 FPDFImageObj_GetImageFilter(obj, 0, buf.data(), len));
3897 EXPECT_STREQ(kFlateDecode, buf.data());
Jane Liube63ab92017-08-09 14:09:34 -04003898 EXPECT_EQ(0u, FPDFImageObj_GetImageFilter(obj, 1, nullptr, 0));
3899
3900 // Verify all the filters for an image object with a list of filters.
3901 obj = FPDFPage_GetObject(page, 38);
3902 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3903 ASSERT_EQ(2, FPDFImageObj_GetImageFilterCount(obj));
3904 len = FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0);
3905 buf.clear();
3906 buf.resize(len);
Lei Zhang0733a1b2017-08-31 12:36:31 -07003907 static constexpr char kASCIIHexDecode[] = "ASCIIHexDecode";
3908 EXPECT_EQ(sizeof(kASCIIHexDecode),
3909 FPDFImageObj_GetImageFilter(obj, 0, buf.data(), len));
3910 EXPECT_STREQ(kASCIIHexDecode, buf.data());
Jane Liube63ab92017-08-09 14:09:34 -04003911
3912 len = FPDFImageObj_GetImageFilter(obj, 1, nullptr, 0);
3913 buf.clear();
3914 buf.resize(len);
Lei Zhang0733a1b2017-08-31 12:36:31 -07003915 static constexpr char kDCTDecode[] = "DCTDecode";
3916 EXPECT_EQ(sizeof(kDCTDecode),
3917 FPDFImageObj_GetImageFilter(obj, 1, buf.data(), len));
3918 EXPECT_STREQ(kDCTDecode, buf.data());
Jane Liube63ab92017-08-09 14:09:34 -04003919
3920 UnloadPage(page);
3921}
Jane Liuca898292017-08-16 11:25:35 -04003922
Lei Zhangab41f252018-12-23 03:10:50 +00003923TEST_F(FPDFEditEmbedderTest, GetImageMetadata) {
Jane Liuca898292017-08-16 11:25:35 -04003924 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3925 FPDF_PAGE page = LoadPage(0);
3926 ASSERT_TRUE(page);
3927
3928 // Check that getting the metadata of a null object would fail.
3929 FPDF_IMAGEOBJ_METADATA metadata;
3930 EXPECT_FALSE(FPDFImageObj_GetImageMetadata(nullptr, page, &metadata));
3931
3932 // Check that receiving the metadata with a null metadata object would fail.
3933 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 35);
3934 EXPECT_FALSE(FPDFImageObj_GetImageMetadata(obj, page, nullptr));
3935
3936 // Check that when retrieving an image object's metadata without passing in
3937 // |page|, all values are correct, with the last two being default values.
3938 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3939 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, nullptr, &metadata));
Julian Lungerecd063e2017-12-27 10:18:50 -05003940 EXPECT_EQ(7, metadata.marked_content_id);
Jane Liuca898292017-08-16 11:25:35 -04003941 EXPECT_EQ(92u, metadata.width);
3942 EXPECT_EQ(68u, metadata.height);
Lei Zhang351e8b02018-12-20 01:10:06 +00003943 EXPECT_FLOAT_EQ(96.0f, metadata.horizontal_dpi);
3944 EXPECT_FLOAT_EQ(96.0f, metadata.vertical_dpi);
Jane Liuca898292017-08-16 11:25:35 -04003945 EXPECT_EQ(0u, metadata.bits_per_pixel);
3946 EXPECT_EQ(FPDF_COLORSPACE_UNKNOWN, metadata.colorspace);
3947
3948 // Verify the metadata of a bitmap image with indexed colorspace.
3949 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata));
Julian Lungerecd063e2017-12-27 10:18:50 -05003950 EXPECT_EQ(7, metadata.marked_content_id);
Jane Liuca898292017-08-16 11:25:35 -04003951 EXPECT_EQ(92u, metadata.width);
3952 EXPECT_EQ(68u, metadata.height);
Lei Zhang351e8b02018-12-20 01:10:06 +00003953 EXPECT_FLOAT_EQ(96.0f, metadata.horizontal_dpi);
3954 EXPECT_FLOAT_EQ(96.0f, metadata.vertical_dpi);
Jane Liuca898292017-08-16 11:25:35 -04003955 EXPECT_EQ(1u, metadata.bits_per_pixel);
3956 EXPECT_EQ(FPDF_COLORSPACE_INDEXED, metadata.colorspace);
3957
3958 // Verify the metadata of an image with RGB colorspace.
3959 obj = FPDFPage_GetObject(page, 37);
3960 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3961 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata));
Julian Lungerecd063e2017-12-27 10:18:50 -05003962 EXPECT_EQ(9, metadata.marked_content_id);
Jane Liuca898292017-08-16 11:25:35 -04003963 EXPECT_EQ(126u, metadata.width);
3964 EXPECT_EQ(106u, metadata.height);
Lei Zhang351e8b02018-12-20 01:10:06 +00003965 EXPECT_FLOAT_EQ(162.173752f, metadata.horizontal_dpi);
3966 EXPECT_FLOAT_EQ(162.555878f, metadata.vertical_dpi);
Jane Liuca898292017-08-16 11:25:35 -04003967 EXPECT_EQ(24u, metadata.bits_per_pixel);
3968 EXPECT_EQ(FPDF_COLORSPACE_DEVICERGB, metadata.colorspace);
3969
3970 UnloadPage(page);
3971}
Lei Zhangdc1b7392020-05-14 21:15:53 +00003972
3973TEST_F(FPDFEditEmbedderTest, GetImageMetadataJpxLzw) {
3974 ASSERT_TRUE(OpenDocument("jpx_lzw.pdf"));
3975 FPDF_PAGE page = LoadPage(0);
3976 ASSERT_TRUE(page);
3977
3978 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
3979 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3980
3981 FPDF_IMAGEOBJ_METADATA metadata;
3982 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata));
3983 EXPECT_EQ(-1, metadata.marked_content_id);
3984 EXPECT_EQ(612u, metadata.width);
3985 EXPECT_EQ(792u, metadata.height);
3986 EXPECT_FLOAT_EQ(72.0f, metadata.horizontal_dpi);
3987 EXPECT_FLOAT_EQ(72.0f, metadata.vertical_dpi);
3988 EXPECT_EQ(24u, metadata.bits_per_pixel);
3989 EXPECT_EQ(FPDF_COLORSPACE_UNKNOWN, metadata.colorspace);
3990
3991 UnloadPage(page);
3992}