blob: e7cda4b02520b1c76299a105d8fd4be6853c9119 [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"
Miklos Vajna46b43732018-08-14 19:15:43 +000012#include "core/fpdfapi/page/cpdf_formobject.h"
Nicolas Penaa4ad01f2017-02-15 16:26:48 -050013#include "core/fpdfapi/page/cpdf_page.h"
Henrique Nakashima6eb79392018-06-12 20:27:35 +000014#include "core/fpdfapi/page/cpdf_pageobject.h"
Nicolas Penabe90aae2017-02-27 10:41:41 -050015#include "core/fpdfapi/parser/cpdf_array.h"
Nicolas Penaa4ad01f2017-02-15 16:26:48 -050016#include "core/fpdfapi/parser/cpdf_dictionary.h"
Nicolas Penad03ca422017-03-06 13:54:33 -050017#include "core/fpdfapi/parser/cpdf_number.h"
Nicolas Penabe90aae2017-02-27 10:41:41 -050018#include "core/fpdfapi/parser/cpdf_stream.h"
Artem Strygineababa12018-06-06 12:31:18 +000019#include "core/fpdfapi/parser/cpdf_stream_acc.h"
Nicolas Pena0fc185e2017-02-08 12:13:20 -050020#include "core/fxcrt/fx_system.h"
Lei Zhang0dcb8fd2019-02-07 00:46:04 +000021#include "core/fxge/fx_font.h"
Dan Sinclair00d47a62018-03-28 18:39:04 +000022#include "fpdfsdk/cpdfsdk_helpers.h"
Tom Sepeze08d2b12018-04-25 18:49:32 +000023#include "public/cpp/fpdf_scopers.h"
Jane Liueda65252017-06-07 11:31:27 -040024#include "public/fpdf_annot.h"
Tom Sepezd483eb42016-01-06 10:03:59 -080025#include "public/fpdf_edit.h"
26#include "public/fpdfview.h"
27#include "testing/embedder_test.h"
Hui Yingstb4baceb2020-04-28 23:46:10 +000028#include "testing/embedder_test_constants.h"
Lei Zhangb6992dd2019-02-05 23:30:20 +000029#include "testing/fx_string_testhelpers.h"
Tom Sepez0aec19b2016-01-07 12:22:44 -080030#include "testing/gmock/include/gmock/gmock-matchers.h"
Tom Sepezd483eb42016-01-06 10:03:59 -080031#include "testing/gtest/include/gtest/gtest.h"
Hui Yingst8e88e382020-11-02 18:19:56 +000032#include "testing/utils/file_util.h"
Lei Zhang4c64e962019-02-05 19:24:12 +000033#include "testing/utils/hash.h"
Hui Yingst8e88e382020-11-02 18:19:56 +000034#include "testing/utils/path_service.h"
Tom 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
44#if defined(OS_WIN)
45const char kBottomTextChecksum[] = "08d1ff3e5a42801bee6077fd366bef00";
Lei Zhang0c03d632020-07-30 17:05:36 +000046#elif defined(OS_APPLE)
Hui Yingst3b6136a2020-06-09 00:39:33 +000047const char kBottomTextChecksum[] = "324e1db8164a040cf6104538baa95ba6";
48#else
49const char kBottomTextChecksum[] = "eacaa24573b8ce997b3882595f096f00";
50#endif
Hui Yingstb4baceb2020-04-28 23:46:10 +000051
Hui Yingst08c40712020-04-29 01:37:35 +000052#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
53#if defined(OS_WIN)
54const char kFirstRemovedChecksum[] = "d468228cc55071a9e838f66afc0f58ff";
55#else
56const char kFirstRemovedChecksum[] = "0c79dc1065b1d06991e3ac4aaa35d25c";
57#endif // defined(OS_WIN)
58#else
Hui Yingstb4baceb2020-04-28 23:46:10 +000059#if defined(OS_WIN)
60const char kFirstRemovedChecksum[] = "aae6c5334721f90ec30d3d59f4ef7deb";
Lei Zhang0c03d632020-07-30 17:05:36 +000061#elif defined(OS_APPLE)
Hui Yingstb4baceb2020-04-28 23:46:10 +000062const char kFirstRemovedChecksum[] = "17ca3778fd8bb395b46532f1fa17f702";
63#else
64const char kFirstRemovedChecksum[] = "b76df015fe88009c3c342395df96abf1";
65#endif
Hui Yingst08c40712020-04-29 01:37:35 +000066#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingstb4baceb2020-04-28 23:46:10 +000067
Hui Yingst3b6136a2020-06-09 00:39:33 +000068const wchar_t kLoadedFontText[] = L"I am testing my loaded font, WEE.";
69
70#if defined(OS_WIN)
71const char kLoadedFontTextChecksum[] = "d60ba39f9698e32360d99e727dd93165";
Lei Zhang0c03d632020-07-30 17:05:36 +000072#elif defined(OS_APPLE)
Hui Yingst3b6136a2020-06-09 00:39:33 +000073const char kLoadedFontTextChecksum[] = "fc921c0bbdde73986ac13c15a85db4c3";
74#else
75const char kLoadedFontTextChecksum[] = "70592859010ffbf532a2237b8118bcc4";
76#endif
77
78const char kRedRectangleChecksum[] = "66d02eaa6181e2c069ce2ea99beda497";
79
Lei Zhang85166512020-07-14 23:28:56 +000080// In embedded_images.pdf.
81const char kEmbeddedImage33Checksum[] = "cb3637934bb3b95a6e4ae1ea9eb9e56e";
82
Hui Yingstb4baceb2020-04-28 23:46:10 +000083} // namespace
84
Lei Zhangab41f252018-12-23 03:10:50 +000085class FPDFEditEmbedderTest : public EmbedderTest {
Nicolas Penad03ca422017-03-06 13:54:33 -050086 protected:
87 FPDF_DOCUMENT CreateNewDocument() {
88 document_ = FPDF_CreateNewDocument();
Tom Sepez41066c12017-05-18 09:28:49 -070089 cpdf_doc_ = CPDFDocumentFromFPDFDocument(document_);
Nicolas Penad03ca422017-03-06 13:54:33 -050090 return document_;
91 }
92
Lei Zhang710fa992018-05-25 16:24:48 +000093 void CheckFontDescriptor(const CPDF_Dictionary* font_dict,
Nicolas Penad03ca422017-03-06 13:54:33 -050094 int font_type,
95 bool bold,
96 bool italic,
Tom Sepez20c41a52018-08-29 23:53:53 +000097 pdfium::span<const uint8_t> span) {
Lei Zhangb1ec2802018-05-25 21:55:24 +000098 const CPDF_Dictionary* font_desc = font_dict->GetDictFor("FontDescriptor");
Nicolas Penad03ca422017-03-06 13:54:33 -050099 ASSERT_TRUE(font_desc);
Lei Zhanga228ff32020-06-24 17:39:33 +0000100 EXPECT_EQ("FontDescriptor", font_desc->GetNameFor("Type"));
101 ByteString font_name = font_desc->GetNameFor("FontName");
102 EXPECT_FALSE(font_name.IsEmpty());
103 EXPECT_EQ(font_dict->GetNameFor("BaseFont"), font_name);
Nicolas Penad03ca422017-03-06 13:54:33 -0500104
105 // Check that the font descriptor has the required keys according to spec
106 // 1.7 Table 5.19
107 ASSERT_TRUE(font_desc->KeyExist("Flags"));
Dan Sinclair10e1f052017-09-28 15:59:42 -0400108
Nicolas Penad03ca422017-03-06 13:54:33 -0500109 int font_flags = font_desc->GetIntegerFor("Flags");
Lei Zhang44d03832019-10-18 18:45:31 +0000110 EXPECT_EQ(bold, FontStyleIsForceBold(font_flags));
Dan Sinclair10e1f052017-09-28 15:59:42 -0400111 EXPECT_EQ(italic, FontStyleIsItalic(font_flags));
112 EXPECT_TRUE(FontStyleIsNonSymbolic(font_flags));
Nicolas Penad03ca422017-03-06 13:54:33 -0500113 ASSERT_TRUE(font_desc->KeyExist("FontBBox"));
Nicolás Peña5f95f362017-09-28 13:00:45 +0900114
Lei Zhangb1ec2802018-05-25 21:55:24 +0000115 const CPDF_Array* fontBBox = font_desc->GetArrayFor("FontBBox");
Nicolás Peña5f95f362017-09-28 13:00:45 +0900116 ASSERT_TRUE(fontBBox);
Lei Zhangf40380f2018-10-12 18:31:51 +0000117 EXPECT_EQ(4u, fontBBox->size());
Nicolás Peña5f95f362017-09-28 13:00:45 +0900118 // Check that the coordinates are in the preferred order according to spec
119 // 1.7 Section 3.8.4
120 EXPECT_TRUE(fontBBox->GetIntegerAt(0) < fontBBox->GetIntegerAt(2));
121 EXPECT_TRUE(fontBBox->GetIntegerAt(1) < fontBBox->GetIntegerAt(3));
122
Nicolas Penad03ca422017-03-06 13:54:33 -0500123 EXPECT_TRUE(font_desc->KeyExist("ItalicAngle"));
124 EXPECT_TRUE(font_desc->KeyExist("Ascent"));
125 EXPECT_TRUE(font_desc->KeyExist("Descent"));
126 EXPECT_TRUE(font_desc->KeyExist("CapHeight"));
127 EXPECT_TRUE(font_desc->KeyExist("StemV"));
Ryan Harrison275e2602017-09-18 14:23:18 -0400128 ByteString present("FontFile");
129 ByteString absent("FontFile2");
Nicolas Penad03ca422017-03-06 13:54:33 -0500130 if (font_type == FPDF_FONT_TRUETYPE)
131 std::swap(present, absent);
132 EXPECT_TRUE(font_desc->KeyExist(present));
133 EXPECT_FALSE(font_desc->KeyExist(absent));
134
Artem Strygineababa12018-06-06 12:31:18 +0000135 auto streamAcc =
136 pdfium::MakeRetain<CPDF_StreamAcc>(font_desc->GetStreamFor(present));
137 streamAcc->LoadAllDataRaw();
138
Nicolas Penad03ca422017-03-06 13:54:33 -0500139 // Check that the font stream is the one that was provided
Tom Sepez20c41a52018-08-29 23:53:53 +0000140 ASSERT_EQ(span.size(), streamAcc->GetSize());
Nicolás Peña79eab232017-09-28 13:29:05 +0900141 if (font_type == FPDF_FONT_TRUETYPE) {
Tom Sepez20c41a52018-08-29 23:53:53 +0000142 ASSERT_EQ(static_cast<int>(span.size()),
Artem Strygineababa12018-06-06 12:31:18 +0000143 streamAcc->GetDict()->GetIntegerFor("Length1"));
Nicolás Peña79eab232017-09-28 13:29:05 +0900144 }
Artem Strygineababa12018-06-06 12:31:18 +0000145
146 const uint8_t* stream_data = streamAcc->GetData();
Tom Sepez20c41a52018-08-29 23:53:53 +0000147 for (size_t j = 0; j < span.size(); j++)
148 EXPECT_EQ(span[j], stream_data[j]) << " at byte " << j;
Nicolas Penad03ca422017-03-06 13:54:33 -0500149 }
150
Lei Zhangde579ab2018-05-25 21:49:49 +0000151 void CheckCompositeFontWidths(const CPDF_Array* widths_array,
Nicolas Penad03ca422017-03-06 13:54:33 -0500152 CPDF_Font* typed_font) {
153 // Check that W array is in a format that conforms to PDF spec 1.7 section
154 // "Glyph Metrics in CIDFonts" (these checks are not
155 // implementation-specific).
Lei Zhangf40380f2018-10-12 18:31:51 +0000156 EXPECT_GT(widths_array->size(), 1u);
Nicolas Penad03ca422017-03-06 13:54:33 -0500157 int num_cids_checked = 0;
158 int cur_cid = 0;
Lei Zhangf40380f2018-10-12 18:31:51 +0000159 for (size_t idx = 0; idx < widths_array->size(); idx++) {
Nicolas Penad03ca422017-03-06 13:54:33 -0500160 int cid = widths_array->GetNumberAt(idx);
161 EXPECT_GE(cid, cur_cid);
Lei Zhangf40380f2018-10-12 18:31:51 +0000162 ASSERT_FALSE(++idx == widths_array->size());
Lei Zhangde579ab2018-05-25 21:49:49 +0000163 const CPDF_Object* next = widths_array->GetObjectAt(idx);
Nicolas Penad03ca422017-03-06 13:54:33 -0500164 if (next->IsArray()) {
165 // We are in the c [w1 w2 ...] case
Lei Zhangde579ab2018-05-25 21:49:49 +0000166 const CPDF_Array* arr = next->AsArray();
Lei Zhangf40380f2018-10-12 18:31:51 +0000167 int cnt = static_cast<int>(arr->size());
Nicolas Penad03ca422017-03-06 13:54:33 -0500168 size_t inner_idx = 0;
169 for (cur_cid = cid; cur_cid < cid + cnt; cur_cid++) {
Lei Zhang70e66192020-09-18 20:50:51 +0000170 int width = arr->GetNumberAt(inner_idx++);
Dan Sinclair971a6742018-03-28 19:23:25 +0000171 EXPECT_EQ(width, typed_font->GetCharWidthF(cur_cid))
172 << " at cid " << cur_cid;
Nicolas Penad03ca422017-03-06 13:54:33 -0500173 }
174 num_cids_checked += cnt;
175 continue;
176 }
177 // Otherwise, are in the c_first c_last w case.
178 ASSERT_TRUE(next->IsNumber());
179 int last_cid = next->AsNumber()->GetInteger();
Lei Zhangf40380f2018-10-12 18:31:51 +0000180 ASSERT_FALSE(++idx == widths_array->size());
Lei Zhang70e66192020-09-18 20:50:51 +0000181 int width = widths_array->GetNumberAt(idx);
Nicolas Penad03ca422017-03-06 13:54:33 -0500182 for (cur_cid = cid; cur_cid <= last_cid; cur_cid++) {
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 += last_cid - cid + 1;
187 }
188 // Make sure we have a good amount of cids described
189 EXPECT_GT(num_cids_checked, 900);
190 }
191 CPDF_Document* cpdf_doc() { return cpdf_doc_; }
192
193 private:
194 CPDF_Document* cpdf_doc_;
195};
Tom Sepezd483eb42016-01-06 10:03:59 -0800196
etienneb7712c262016-04-26 08:13:45 -0700197namespace {
thestigdc7ec032016-11-21 15:32:52 -0800198
etienneb7712c262016-04-26 08:13:45 -0700199const char kExpectedPDF[] =
200 "%PDF-1.7\r\n"
201 "%\xA1\xB3\xC5\xD7\r\n"
202 "1 0 obj\r\n"
203 "<</Pages 2 0 R /Type/Catalog>>\r\n"
204 "endobj\r\n"
205 "2 0 obj\r\n"
206 "<</Count 1/Kids\\[ 4 0 R \\]/Type/Pages>>\r\n"
207 "endobj\r\n"
208 "3 0 obj\r\n"
209 "<</CreationDate\\(D:.*\\)/Creator\\(PDFium\\)>>\r\n"
210 "endobj\r\n"
211 "4 0 obj\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400212 "<</MediaBox\\[ 0 0 640 480\\]/Parent 2 0 R "
213 "/Resources<</ExtGState<</FXE1 5 0 R >>>>"
Nicolas Penad9d6c292017-06-06 16:12:10 -0400214 "/Rotate 0/Type/Page"
etienneb7712c262016-04-26 08:13:45 -0700215 ">>\r\n"
216 "endobj\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400217 "5 0 obj\r\n"
218 "<</BM/Normal/CA 1/ca 1>>\r\n"
219 "endobj\r\n"
etienneb7712c262016-04-26 08:13:45 -0700220 "xref\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400221 "0 6\r\n"
etienneb7712c262016-04-26 08:13:45 -0700222 "0000000000 65535 f\r\n"
223 "0000000017 00000 n\r\n"
224 "0000000066 00000 n\r\n"
225 "0000000122 00000 n\r\n"
226 "0000000192 00000 n\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400227 "0000000311 00000 n\r\n"
etienneb7712c262016-04-26 08:13:45 -0700228 "trailer\r\n"
229 "<<\r\n"
230 "/Root 1 0 R\r\n"
231 "/Info 3 0 R\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400232 "/Size 6/ID\\[<.*><.*>\\]>>\r\n"
etienneb7712c262016-04-26 08:13:45 -0700233 "startxref\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400234 "354\r\n"
etienneb7712c262016-04-26 08:13:45 -0700235 "%%EOF\r\n";
thestigdc7ec032016-11-21 15:32:52 -0800236
etienneb7712c262016-04-26 08:13:45 -0700237} // namespace
238
Hui Yingst8e88e382020-11-02 18:19:56 +0000239TEST_F(FPDFEditEmbedderTest, EmbedNotoSansSCFont) {
240 EXPECT_TRUE(CreateEmptyDocument());
241 ScopedFPDFPage page(FPDFPage_New(document(), 0, 400, 400));
242 std::string font_path;
Hui Yingst8532ef02020-11-04 19:17:17 +0000243 ASSERT_TRUE(PathService::GetThirdPartyFilePath(
244 "NotoSansCJK/NotoSansSC-Regular.subset.otf", &font_path));
Hui Yingst8e88e382020-11-02 18:19:56 +0000245
246 size_t file_length = 0;
247 std::unique_ptr<char, pdfium::FreeDeleter> font_data =
248 GetFileContents(font_path.c_str(), &file_length);
249 ASSERT(font_data);
250
251 ScopedFPDFFont font(FPDFText_LoadFont(
252 document(), reinterpret_cast<const uint8_t*>(font_data.get()),
253 file_length, FPDF_FONT_TRUETYPE, /*cid=*/true));
254 FPDF_PAGEOBJECT text_object =
255 FPDFPageObj_CreateTextObj(document(), font.get(), 20.0f);
256 EXPECT_TRUE(text_object);
257
258 // Test the characters which are either mapped to one single unicode or
259 // multiple unicodes in the embedded font.
260 ScopedFPDFWideString text = GetFPDFWideString(L"这是第一句。 这是第二行。");
261 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
262
263 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 50, 200);
264 FPDFPage_InsertObject(page.get(), text_object);
265 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
266
267#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
268#if defined(OS_APPLE)
269 const char kChecksum[] = "9a31fb87d1c6d2346bba22d1196041cd";
270#else
271 const char kChecksum[] = "5bb65e15fc0a685934cd5006dec08a76";
272#endif // defined(OS_APPLE)
273#else
274#if defined(OS_WIN)
275 const char kChecksum[] = "89e8eef5d6ad18c542a92a0519954d0f";
276#else
277 const char kChecksum[] = "9a31fb87d1c6d2346bba22d1196041cd";
278#endif // defined(OS_WIN)
279#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
280 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
281 CompareBitmap(page_bitmap.get(), 400, 400, kChecksum);
282
283 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
284 VerifySavedDocument(400, 400, kChecksum);
285}
286
Lei Zhangab41f252018-12-23 03:10:50 +0000287TEST_F(FPDFEditEmbedderTest, EmptyCreation) {
Tom Sepezd483eb42016-01-06 10:03:59 -0800288 EXPECT_TRUE(CreateEmptyDocument());
weili9b777de2016-08-19 16:19:46 -0700289 FPDF_PAGE page = FPDFPage_New(document(), 0, 640.0, 480.0);
Tom Sepezd483eb42016-01-06 10:03:59 -0800290 EXPECT_NE(nullptr, page);
Nicolas Penad9d6c292017-06-06 16:12:10 -0400291 // The FPDFPage_GenerateContent call should do nothing.
Tom Sepezd483eb42016-01-06 10:03:59 -0800292 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Tom Sepez0aec19b2016-01-07 12:22:44 -0800293 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
etienneb7712c262016-04-26 08:13:45 -0700294
Nicolas Penad9d6c292017-06-06 16:12:10 -0400295 EXPECT_THAT(GetString(), testing::MatchesRegex(std::string(
296 kExpectedPDF, sizeof(kExpectedPDF))));
weili9b777de2016-08-19 16:19:46 -0700297 FPDF_ClosePage(page);
Tom Sepezd483eb42016-01-06 10:03:59 -0800298}
thestigdc7ec032016-11-21 15:32:52 -0800299
300// Regression test for https://crbug.com/667012
Lei Zhangab41f252018-12-23 03:10:50 +0000301TEST_F(FPDFEditEmbedderTest, RasterizePDF) {
thestigdc7ec032016-11-21 15:32:52 -0800302 const char kAllBlackMd5sum[] = "5708fc5c4a8bd0abde99c8e8f0390615";
303
Lei Zhangf0542892019-01-17 18:46:27 +0000304 // Get the bitmap for the original document.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000305 ScopedFPDFBitmap orig_bitmap;
thestigdc7ec032016-11-21 15:32:52 -0800306 {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000307 ASSERT_TRUE(OpenDocument("black.pdf"));
thestigdc7ec032016-11-21 15:32:52 -0800308 FPDF_PAGE orig_page = LoadPage(0);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000309 ASSERT_TRUE(orig_page);
310 orig_bitmap = RenderLoadedPage(orig_page);
311 CompareBitmap(orig_bitmap.get(), 612, 792, kAllBlackMd5sum);
thestigdc7ec032016-11-21 15:32:52 -0800312 UnloadPage(orig_page);
313 }
314
315 // Create a new document from |orig_bitmap| and save it.
316 {
317 FPDF_DOCUMENT temp_doc = FPDF_CreateNewDocument();
318 FPDF_PAGE temp_page = FPDFPage_New(temp_doc, 0, 612, 792);
319
320 // Add the bitmap to an image object and add the image object to the output
321 // page.
Lei Zhangcbd89572017-03-15 17:35:47 -0700322 FPDF_PAGEOBJECT temp_img = FPDFPageObj_NewImageObj(temp_doc);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000323 EXPECT_TRUE(
324 FPDFImageObj_SetBitmap(&temp_page, 1, temp_img, orig_bitmap.get()));
thestigdc7ec032016-11-21 15:32:52 -0800325 EXPECT_TRUE(FPDFImageObj_SetMatrix(temp_img, 612, 0, 0, 792, 0, 0));
326 FPDFPage_InsertObject(temp_page, temp_img);
327 EXPECT_TRUE(FPDFPage_GenerateContent(temp_page));
328 EXPECT_TRUE(FPDF_SaveAsCopy(temp_doc, this, 0));
329 FPDF_ClosePage(temp_page);
330 FPDF_CloseDocument(temp_doc);
331 }
thestigdc7ec032016-11-21 15:32:52 -0800332
333 // Get the generated content. Make sure it is at least as big as the original
334 // PDF.
Lei Zhangd72fd582018-07-27 19:37:27 +0000335 EXPECT_GT(GetString().size(), 923u);
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400336 VerifySavedDocument(612, 792, kAllBlackMd5sum);
thestigdc7ec032016-11-21 15:32:52 -0800337}
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500338
Lei Zhang03e5e682019-09-16 19:45:55 +0000339// TODO(crbug.com/pdfium/11): Fix this test and enable.
340#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
341#define MAYBE_AddPaths DISABLED_AddPaths
342#else
343#define MAYBE_AddPaths AddPaths
344#endif
345TEST_F(FPDFEditEmbedderTest, MAYBE_AddPaths) {
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500346 // Start with a blank page
Nicolas Penad03ca422017-03-06 13:54:33 -0500347 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000348 ASSERT_TRUE(page);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500349
350 // We will first add a red rectangle
351 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000352 ASSERT_TRUE(red_rect);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500353 // Expect false when trying to set colors out of range
Lei Zhang3475b482019-05-13 18:30:57 +0000354 EXPECT_FALSE(FPDFPageObj_SetStrokeColor(red_rect, 100, 100, 100, 300));
355 EXPECT_FALSE(FPDFPageObj_SetFillColor(red_rect, 200, 256, 200, 0));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500356
357 // Fill rectangle with red and insert to the page
Lei Zhang3475b482019-05-13 18:30:57 +0000358 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500359 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
Miklos Vajna491112b2018-05-30 13:30:10 +0000360
361 int fillmode = FPDF_FILLMODE_NONE;
362 FPDF_BOOL stroke = true;
363 EXPECT_TRUE(FPDFPath_GetDrawMode(red_rect, &fillmode, &stroke));
364 EXPECT_EQ(FPDF_FILLMODE_ALTERNATE, fillmode);
365 EXPECT_FALSE(stroke);
366
Lei Zhang8da98232019-12-11 23:29:33 +0000367 static const FS_MATRIX kMatrix = {1, 2, 3, 4, 5, 6};
368 EXPECT_FALSE(FPDFPath_SetMatrix(nullptr, &kMatrix));
369 EXPECT_TRUE(FPDFPath_SetMatrix(red_rect, &kMatrix));
370
371 FS_MATRIX matrix;
372 EXPECT_FALSE(FPDFPath_GetMatrix(nullptr, &matrix));
373 EXPECT_TRUE(FPDFPath_GetMatrix(red_rect, &matrix));
374 EXPECT_FLOAT_EQ(1.0f, matrix.a);
375 EXPECT_FLOAT_EQ(2.0f, matrix.b);
376 EXPECT_FLOAT_EQ(3.0f, matrix.c);
377 EXPECT_FLOAT_EQ(4.0f, matrix.d);
378 EXPECT_FLOAT_EQ(5.0f, matrix.e);
379 EXPECT_FLOAT_EQ(6.0f, matrix.f);
380
381 // Set back the identity matrix.
382 matrix = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
383 EXPECT_TRUE(FPDFPath_SetMatrix(red_rect, &matrix));
Miklos Vajna97f4d672018-06-04 14:47:17 +0000384
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500385 FPDFPage_InsertObject(page, red_rect);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000386 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000387 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +0000388 CompareBitmap(page_bitmap.get(), 612, 792, kRedRectangleChecksum);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000389 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500390
391 // Now add to that a green rectangle with some medium alpha
392 FPDF_PAGEOBJECT green_rect = FPDFPageObj_CreateNewRect(100, 100, 40, 40);
Lei Zhang3475b482019-05-13 18:30:57 +0000393 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_rect, 0, 255, 0, 128));
Miklos Vajnaed4705b2017-04-05 09:24:50 +0200394
Miklos Vajna1ef04c92017-05-08 18:14:19 +0200395 // Make sure the type of the rectangle is a path.
396 EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(green_rect));
397
Miklos Vajnaed4705b2017-04-05 09:24:50 +0200398 // Make sure we get back the same color we set previously.
399 unsigned int R;
400 unsigned int G;
401 unsigned int B;
402 unsigned int A;
Lei Zhang3475b482019-05-13 18:30:57 +0000403 EXPECT_TRUE(FPDFPageObj_GetFillColor(green_rect, &R, &G, &B, &A));
Lei Zhangd72fd582018-07-27 19:37:27 +0000404 EXPECT_EQ(0u, R);
405 EXPECT_EQ(255u, G);
406 EXPECT_EQ(0u, B);
407 EXPECT_EQ(128u, A);
Miklos Vajnaed4705b2017-04-05 09:24:50 +0200408
Miklos Vajna12abfd02017-09-15 07:49:03 +0200409 // Make sure the path has 5 points (1 FXPT_TYPE::MoveTo and 4
410 // FXPT_TYPE::LineTo).
Miklos Vajna0150a542017-09-21 21:46:56 +0200411 ASSERT_EQ(5, FPDFPath_CountSegments(green_rect));
Miklos Vajna36eed872017-09-20 22:52:43 +0200412 // Verify actual coordinates.
413 FPDF_PATHSEGMENT segment = FPDFPath_GetPathSegment(green_rect, 0);
414 float x;
415 float y;
416 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
417 EXPECT_EQ(100, x);
418 EXPECT_EQ(100, y);
419 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
420 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
421 segment = FPDFPath_GetPathSegment(green_rect, 1);
422 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
423 EXPECT_EQ(100, x);
424 EXPECT_EQ(140, y);
425 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
426 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
427 segment = FPDFPath_GetPathSegment(green_rect, 2);
428 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
429 EXPECT_EQ(140, x);
430 EXPECT_EQ(140, y);
431 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
432 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
433 segment = FPDFPath_GetPathSegment(green_rect, 3);
434 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
435 EXPECT_EQ(140, x);
436 EXPECT_EQ(100, y);
437 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
438 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
439 segment = FPDFPath_GetPathSegment(green_rect, 4);
440 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
441 EXPECT_EQ(100, x);
442 EXPECT_EQ(100, y);
443 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
444 EXPECT_TRUE(FPDFPathSegment_GetClose(segment));
Miklos Vajna12abfd02017-09-15 07:49:03 +0200445
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500446 EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect, FPDF_FILLMODE_WINDING, 0));
447 FPDFPage_InsertObject(page, green_rect);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000448 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000449 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000450 CompareBitmap(page_bitmap.get(), 612, 792,
451 "7b0b87604594e773add528fae567a558");
452 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500453
454 // Add a black triangle.
455 FPDF_PAGEOBJECT black_path = FPDFPageObj_CreateNewPath(400, 100);
Lei Zhang3475b482019-05-13 18:30:57 +0000456 EXPECT_TRUE(FPDFPageObj_SetFillColor(black_path, 0, 0, 0, 200));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500457 EXPECT_TRUE(FPDFPath_SetDrawMode(black_path, FPDF_FILLMODE_ALTERNATE, 0));
458 EXPECT_TRUE(FPDFPath_LineTo(black_path, 400, 200));
459 EXPECT_TRUE(FPDFPath_LineTo(black_path, 300, 100));
460 EXPECT_TRUE(FPDFPath_Close(black_path));
Miklos Vajna12abfd02017-09-15 07:49:03 +0200461
462 // Make sure the path has 3 points (1 FXPT_TYPE::MoveTo and 2
463 // FXPT_TYPE::LineTo).
Miklos Vajna0150a542017-09-21 21:46:56 +0200464 ASSERT_EQ(3, FPDFPath_CountSegments(black_path));
Miklos Vajna36eed872017-09-20 22:52:43 +0200465 // Verify actual coordinates.
466 segment = FPDFPath_GetPathSegment(black_path, 0);
467 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
468 EXPECT_EQ(400, x);
469 EXPECT_EQ(100, y);
470 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
471 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
472 segment = FPDFPath_GetPathSegment(black_path, 1);
473 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
474 EXPECT_EQ(400, x);
475 EXPECT_EQ(200, y);
476 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
477 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
478 segment = FPDFPath_GetPathSegment(black_path, 2);
479 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
480 EXPECT_EQ(300, x);
481 EXPECT_EQ(100, y);
482 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
483 EXPECT_TRUE(FPDFPathSegment_GetClose(segment));
484 // Make sure out of bounds index access fails properly.
485 EXPECT_EQ(nullptr, FPDFPath_GetPathSegment(black_path, 3));
Miklos Vajna12abfd02017-09-15 07:49:03 +0200486
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500487 FPDFPage_InsertObject(page, black_path);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000488 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000489 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000490 CompareBitmap(page_bitmap.get(), 612, 792,
491 "eadc8020a14dfcf091da2688733d8806");
492 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500493
494 // Now add a more complex blue path.
495 FPDF_PAGEOBJECT blue_path = FPDFPageObj_CreateNewPath(200, 200);
Lei Zhang3475b482019-05-13 18:30:57 +0000496 EXPECT_TRUE(FPDFPageObj_SetFillColor(blue_path, 0, 0, 255, 255));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500497 EXPECT_TRUE(FPDFPath_SetDrawMode(blue_path, FPDF_FILLMODE_WINDING, 0));
498 EXPECT_TRUE(FPDFPath_LineTo(blue_path, 230, 230));
499 EXPECT_TRUE(FPDFPath_BezierTo(blue_path, 250, 250, 280, 280, 300, 300));
500 EXPECT_TRUE(FPDFPath_LineTo(blue_path, 325, 325));
501 EXPECT_TRUE(FPDFPath_LineTo(blue_path, 350, 325));
502 EXPECT_TRUE(FPDFPath_BezierTo(blue_path, 375, 330, 390, 360, 400, 400));
503 EXPECT_TRUE(FPDFPath_Close(blue_path));
504 FPDFPage_InsertObject(page, blue_path);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000505 const char kLastMD5[] = "9823e1a21bd9b72b6a442ba4f12af946";
506 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000507 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000508 CompareBitmap(page_bitmap.get(), 612, 792, kLastMD5);
509 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500510
511 // Now save the result, closing the page and document
Nicolas Pena207b7272017-05-26 17:37:06 -0400512 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Nicolas Penad03ca422017-03-06 13:54:33 -0500513 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500514 FPDF_ClosePage(page);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500515
516 // Render the saved result
Lei Zhang107fa7b2018-02-09 21:48:15 +0000517 VerifySavedDocument(612, 792, kLastMD5);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500518}
519
Miklos Vajna45501f32019-07-30 07:41:02 +0000520TEST_F(FPDFEditEmbedderTest, ClipPath) {
521 // Load document with a clipped rectangle.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000522 ASSERT_TRUE(OpenDocument("clip_path.pdf"));
Miklos Vajna45501f32019-07-30 07:41:02 +0000523 FPDF_PAGE page = LoadPage(0);
524 ASSERT_TRUE(page);
525
526 ASSERT_EQ(1, FPDFPage_CountObjects(page));
527
528 FPDF_PAGEOBJECT triangle = FPDFPage_GetObject(page, 0);
529 ASSERT_TRUE(triangle);
530
531 // Test that we got the expected triangle.
532 ASSERT_EQ(4, FPDFPath_CountSegments(triangle));
533
534 FPDF_PATHSEGMENT segment = FPDFPath_GetPathSegment(triangle, 0);
535 float x;
536 float y;
537 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
538 EXPECT_EQ(10, x);
539 EXPECT_EQ(10, y);
540 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
541 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
542
543 segment = FPDFPath_GetPathSegment(triangle, 1);
544 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
545 EXPECT_EQ(25, x);
546 EXPECT_EQ(40, y);
547 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
548 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
549
550 segment = FPDFPath_GetPathSegment(triangle, 2);
551 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
552 EXPECT_EQ(40, x);
553 EXPECT_EQ(10, y);
554 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
555 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
556
557 segment = FPDFPath_GetPathSegment(triangle, 3);
558 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
559 EXPECT_TRUE(FPDFPathSegment_GetClose(segment));
560
561 // Test FPDFPageObj_GetClipPath().
562 ASSERT_EQ(nullptr, FPDFPageObj_GetClipPath(nullptr));
563
564 FPDF_CLIPPATH clip_path = FPDFPageObj_GetClipPath(triangle);
565 ASSERT_TRUE(clip_path);
566
567 // Test FPDFClipPath_CountPaths().
568 ASSERT_EQ(-1, FPDFClipPath_CountPaths(nullptr));
569 ASSERT_EQ(1, FPDFClipPath_CountPaths(clip_path));
570
571 // Test FPDFClipPath_CountPathSegments().
572 ASSERT_EQ(-1, FPDFClipPath_CountPathSegments(nullptr, 0));
573 ASSERT_EQ(-1, FPDFClipPath_CountPathSegments(clip_path, -1));
574 ASSERT_EQ(-1, FPDFClipPath_CountPathSegments(clip_path, 1));
575 ASSERT_EQ(4, FPDFClipPath_CountPathSegments(clip_path, 0));
576
577 // FPDFClipPath_GetPathSegment() negative testing.
578 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(nullptr, 0, 0));
579 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, -1, 0));
580 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, 1, 0));
581 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, 0, -1));
582 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, 0, 4));
583
584 // FPDFClipPath_GetPathSegment() positive testing.
585 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 0);
586 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
587 EXPECT_EQ(10, x);
588 EXPECT_EQ(15, y);
589 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
590 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
591
592 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 1);
593 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
594 EXPECT_EQ(40, x);
595 EXPECT_EQ(15, y);
596 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
597 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
598
599 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 2);
600 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
601 EXPECT_EQ(40, x);
602 EXPECT_EQ(35, y);
603 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
604 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
605
606 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 3);
607 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
608 EXPECT_EQ(10, x);
609 EXPECT_EQ(35, y);
610 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
611 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
612
613 UnloadPage(page);
614}
615
Lei Zhang571f9322019-09-25 12:40:25 +0000616TEST_F(FPDFEditEmbedderTest, BUG_1399) {
617 // Load document with a clipped rectangle.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000618 ASSERT_TRUE(OpenDocument("bug_1399.pdf"));
Lei Zhang571f9322019-09-25 12:40:25 +0000619 FPDF_PAGE page = LoadPage(0);
620 ASSERT_TRUE(page);
621
622 ASSERT_EQ(7, FPDFPage_CountObjects(page));
623
624 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
625 ASSERT_TRUE(obj);
626
627 ASSERT_EQ(2, FPDFPath_CountSegments(obj));
628
629 FPDF_PATHSEGMENT segment = FPDFPath_GetPathSegment(obj, 0);
630 float x;
631 float y;
632 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
633 EXPECT_FLOAT_EQ(107.718f, x);
634 EXPECT_FLOAT_EQ(719.922f, y);
635 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
636 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
637
638 segment = FPDFPath_GetPathSegment(obj, 1);
639 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
640 EXPECT_FLOAT_EQ(394.718f, x);
641 EXPECT_FLOAT_EQ(719.922f, y);
642 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
643 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
644
645 FPDF_CLIPPATH clip_path = FPDFPageObj_GetClipPath(obj);
646 ASSERT_TRUE(clip_path);
647
648 EXPECT_EQ(-1, FPDFClipPath_CountPaths(clip_path));
649 EXPECT_EQ(-1, FPDFClipPath_CountPathSegments(clip_path, 0));
650 EXPECT_FALSE(FPDFClipPath_GetPathSegment(clip_path, 0, 0));
651
652 UnloadPage(page);
653}
654
Hui Yingstcb4203d2020-06-09 01:48:47 +0000655TEST_F(FPDFEditEmbedderTest, SetText) {
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000656 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000657 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000658 FPDF_PAGE page = LoadPage(0);
659 ASSERT_TRUE(page);
660
661 // Get the "Hello, world!" text object and change it.
662 ASSERT_EQ(2, FPDFPage_CountObjects(page));
663 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
664 ASSERT_TRUE(page_object);
Lei Zhangf0f67682019-04-08 17:03:21 +0000665 ScopedFPDFWideString text1 = GetFPDFWideString(L"Changed for SetText test");
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000666 EXPECT_TRUE(FPDFText_SetText(page_object, text1.get()));
667
668 // Verify the "Hello, world!" text is gone and "Changed for SetText test" is
669 // now displayed.
670 ASSERT_EQ(2, FPDFPage_CountObjects(page));
Hui Yingstcb4203d2020-06-09 01:48:47 +0000671
672#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
673#if defined(OS_WIN)
674 const char kChangedChecksum[] = "119f828345f547c68e9454418fb7d80d";
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000675#else
Hui Yingstcb4203d2020-06-09 01:48:47 +0000676 const char kChangedChecksum[] = "6bc5171f4eb329474989c6ccfa3d6303";
677#endif // defined(OS_WIN)
678#else
679#if defined(OS_WIN)
680 const char kChangedChecksum[] = "3137fdb27962671f5c3963a5e965eff5";
Lei Zhang0c03d632020-07-30 17:05:36 +0000681#elif defined(OS_APPLE)
Hui Yingstcb4203d2020-06-09 01:48:47 +0000682 const char kChangedChecksum[] = "904132275a1144ea06b0694537c80b4c";
683#else
684 const char kChangedChecksum[] = "a0c4ea6620772991f66bf7130379b08a";
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000685#endif
Hui Yingstcb4203d2020-06-09 01:48:47 +0000686#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000687 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000688 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstcb4203d2020-06-09 01:48:47 +0000689 CompareBitmap(page_bitmap.get(), 200, 200, kChangedChecksum);
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000690 }
691
692 // Now save the result.
693 EXPECT_TRUE(FPDFPage_GenerateContent(page));
694 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
695
696 UnloadPage(page);
697
698 // Re-open the file and check the changes were kept in the saved .pdf.
Lei Zhang0b494052019-01-31 21:41:15 +0000699 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000700 FPDF_PAGE saved_page = LoadSavedPage(0);
701 EXPECT_EQ(2, FPDFPage_CountObjects(saved_page));
702 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000703 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstcb4203d2020-06-09 01:48:47 +0000704 CompareBitmap(page_bitmap.get(), 200, 200, kChangedChecksum);
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000705 }
706
707 CloseSavedPage(saved_page);
708 CloseSavedDocument();
709}
710
Hui Yingst822fb8d2020-10-05 22:10:35 +0000711// TODO(crbug.com/pdfium/11): Fix this test and enable.
712#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
713#define MAYBE_SetTextKeepClippingPath DISABLED_SetTextKeepClippingPath
714#else
715#define MAYBE_SetTextKeepClippingPath SetTextKeepClippingPath
716#endif
717TEST_F(FPDFEditEmbedderTest, MAYBE_SetTextKeepClippingPath) {
Daniel Hosseinianda651442020-07-17 23:30:22 +0000718 // Load document with some text, with parts clipped.
719 ASSERT_TRUE(OpenDocument("bug_1558.pdf"));
720 FPDF_PAGE page = LoadPage(0);
721 ASSERT_TRUE(page);
722
723 static constexpr char kOriginalChecksum[] =
724#if defined(OS_WIN)
725 "220bf2086398fc46ac094952b244c8d9";
Lei Zhang0c03d632020-07-30 17:05:36 +0000726#elif defined(OS_APPLE)
Daniel Hosseinianda651442020-07-17 23:30:22 +0000727 "53cbaad93551ef2ccc27ddd63f2ca2b3";
728#else
729 "ba1936fa8ca1e8cca108da76ff3500a6";
730#endif
731 {
732 // When opened before any editing and saving, the clipping path is rendered.
733 ScopedFPDFBitmap original_bitmap = RenderPage(page);
734 CompareBitmap(original_bitmap.get(), 200, 200, kOriginalChecksum);
735 }
736
737 // "Change" the text in the objects to their current values to force them to
738 // regenerate when saving.
739 {
740 ScopedFPDFTextPage text_page(FPDFText_LoadPage(page));
741 ASSERT_TRUE(text_page);
742 const int obj_count = FPDFPage_CountObjects(page);
743 ASSERT_EQ(2, obj_count);
744 for (int i = 0; i < obj_count; ++i) {
745 FPDF_PAGEOBJECT text_obj = FPDFPage_GetObject(page, i);
746 ASSERT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(text_obj));
747 unsigned long size =
748 FPDFTextObj_GetText(text_obj, text_page.get(),
749 /*buffer=*/nullptr, /*length=*/0);
750 ASSERT_GT(size, 0u);
751 std::vector<FPDF_WCHAR> buffer = GetFPDFWideStringBuffer(size);
752 ASSERT_EQ(size, FPDFTextObj_GetText(text_obj, text_page.get(),
753 buffer.data(), size));
754 EXPECT_TRUE(FPDFText_SetText(text_obj, buffer.data()));
755 }
756 }
757
758 {
759 // After editing but before saving, the clipping path is retained.
760 ScopedFPDFBitmap edited_bitmap = RenderPage(page);
761 CompareBitmap(edited_bitmap.get(), 200, 200, kOriginalChecksum);
762 }
763
764 // Save the file.
765 EXPECT_TRUE(FPDFPage_GenerateContent(page));
766 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
767 UnloadPage(page);
768
769 // Open the saved copy and render it.
770 ASSERT_TRUE(OpenSavedDocument());
771 FPDF_PAGE saved_page = LoadSavedPage(0);
772 ASSERT_TRUE(saved_page);
773
774 {
Daniel Hosseinianda651442020-07-17 23:30:22 +0000775 ScopedFPDFBitmap saved_bitmap = RenderSavedPage(saved_page);
Daniel Hosseinian75efd912020-07-21 08:07:28 +0000776 CompareBitmap(saved_bitmap.get(), 200, 200, kOriginalChecksum);
Daniel Hosseinianda651442020-07-17 23:30:22 +0000777 }
778
779 CloseSavedPage(saved_page);
780 CloseSavedDocument();
781}
782
Hui Yingst08c40712020-04-29 01:37:35 +0000783TEST_F(FPDFEditEmbedderTest, RemovePageObject) {
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000784 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000785 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000786 FPDF_PAGE page = LoadPage(0);
787 ASSERT_TRUE(page);
788
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000789 // Show what the original file looks like.
790 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000791 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +0000792 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000793 }
794
795 // Get the "Hello, world!" text object and remove it.
796 ASSERT_EQ(2, FPDFPage_CountObjects(page));
797 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
798 ASSERT_TRUE(page_object);
799 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
800
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000801 // Verify the "Hello, world!" text is gone.
802 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000803 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +0000804 CompareBitmap(page_bitmap.get(), 200, 200, kFirstRemovedChecksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000805 }
806 ASSERT_EQ(1, FPDFPage_CountObjects(page));
807
808 UnloadPage(page);
809 FPDFPageObj_Destroy(page_object);
810}
811
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000812void CheckMarkCounts(FPDF_PAGE page,
813 int start_from,
814 int expected_object_count,
815 size_t expected_prime_count,
816 size_t expected_square_count,
817 size_t expected_greater_than_ten_count,
818 size_t expected_bounds_count) {
819 int object_count = FPDFPage_CountObjects(page);
820 ASSERT_EQ(expected_object_count, object_count);
821
822 size_t prime_count = 0;
823 size_t square_count = 0;
824 size_t greater_than_ten_count = 0;
825 size_t bounds_count = 0;
826 for (int i = 0; i < object_count; ++i) {
827 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
828
829 int mark_count = FPDFPageObj_CountMarks(page_object);
830 for (int j = 0; j < mark_count; ++j) {
831 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
832
833 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +0000834 unsigned long name_len = 999u;
835 ASSERT_TRUE(
836 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
837 EXPECT_GT(name_len, 0u);
838 EXPECT_NE(999u, name_len);
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000839 std::wstring name =
840 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
841 if (name == L"Prime") {
842 prime_count++;
843 } else if (name == L"Square") {
844 square_count++;
845 int expected_square = start_from + i;
846 EXPECT_EQ(1, FPDFPageObjMark_CountParams(mark));
847
Henrique Nakashimac3099d12018-09-18 18:08:15 +0000848 unsigned long get_param_key_return = 999u;
849 ASSERT_TRUE(FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer),
850 &get_param_key_return));
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000851 EXPECT_EQ((6u + 1u) * 2u, get_param_key_return);
852 std::wstring key =
853 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
854 EXPECT_EQ(L"Factor", key);
855
856 EXPECT_EQ(FPDF_OBJECT_NUMBER,
Henrique Nakashima94230e52018-07-11 22:02:02 +0000857 FPDFPageObjMark_GetParamValueType(mark, "Factor"));
Henrique Nakashima140dead2018-07-11 21:40:03 +0000858 int square_root;
Henrique Nakashima94230e52018-07-11 22:02:02 +0000859 EXPECT_TRUE(
860 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &square_root));
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000861 EXPECT_EQ(expected_square, square_root * square_root);
862 } else if (name == L"GreaterThanTen") {
863 greater_than_ten_count++;
864 } else if (name == L"Bounds") {
865 bounds_count++;
866 EXPECT_EQ(1, FPDFPageObjMark_CountParams(mark));
867
Henrique Nakashimac3099d12018-09-18 18:08:15 +0000868 unsigned long get_param_key_return = 999u;
869 ASSERT_TRUE(FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer),
870 &get_param_key_return));
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000871 EXPECT_EQ((8u + 1u) * 2u, get_param_key_return);
872 std::wstring key =
873 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
874 EXPECT_EQ(L"Position", key);
875
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000876 EXPECT_EQ(FPDF_OBJECT_STRING,
Henrique Nakashima94230e52018-07-11 22:02:02 +0000877 FPDFPageObjMark_GetParamValueType(mark, "Position"));
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000878 unsigned long length;
Henrique Nakashimaa3406772018-07-13 19:10:53 +0000879 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
880 mark, "Position", buffer, sizeof(buffer), &length));
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000881 ASSERT_GT(length, 0u);
Henrique Nakashima140dead2018-07-11 21:40:03 +0000882 std::wstring value =
883 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
Henrique Nakashimad8df8c32018-07-12 22:15:09 +0000884
Henrique Nakashimaa3406772018-07-13 19:10:53 +0000885 // "Position" can be "First", "Last", or "End".
Henrique Nakashimad8df8c32018-07-12 22:15:09 +0000886 if (i == 0) {
887 EXPECT_EQ((5u + 1u) * 2u, length);
888 EXPECT_EQ(L"First", value);
889 } else if (i == object_count - 1) {
Henrique Nakashimaa3406772018-07-13 19:10:53 +0000890 if (length == (4u + 1u) * 2u) {
891 EXPECT_EQ(L"Last", value);
892 } else if (length == (3u + 1u) * 2u) {
893 EXPECT_EQ(L"End", value);
894 } else {
895 FAIL();
896 }
Henrique Nakashimad8df8c32018-07-12 22:15:09 +0000897 } else {
898 FAIL();
899 }
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000900 } else {
901 FAIL();
902 }
903 }
904 }
905
906 // Expect certain number of tagged objects. The test file contains strings
907 // from 1 to 19.
908 EXPECT_EQ(expected_prime_count, prime_count);
909 EXPECT_EQ(expected_square_count, square_count);
910 EXPECT_EQ(expected_greater_than_ten_count, greater_than_ten_count);
911 EXPECT_EQ(expected_bounds_count, bounds_count);
912}
913
Lei Zhangab41f252018-12-23 03:10:50 +0000914TEST_F(FPDFEditEmbedderTest, ReadMarkedObjectsIndirectDict) {
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000915 // Load document with some text marked with an indirect property.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000916 ASSERT_TRUE(OpenDocument("text_in_page_marked_indirect.pdf"));
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000917 FPDF_PAGE page = LoadPage(0);
918 ASSERT_TRUE(page);
919
920 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
921
922 UnloadPage(page);
923}
924
Lei Zhang03e5e682019-09-16 19:45:55 +0000925// TODO(crbug.com/pdfium/11): Fix this test and enable.
926#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
927#define MAYBE_RemoveMarkedObjectsPrime DISABLED_RemoveMarkedObjectsPrime
928#else
929#define MAYBE_RemoveMarkedObjectsPrime RemoveMarkedObjectsPrime
930#endif
931TEST_F(FPDFEditEmbedderTest, MAYBE_RemoveMarkedObjectsPrime) {
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000932 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000933 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000934 FPDF_PAGE page = LoadPage(0);
935 ASSERT_TRUE(page);
936
937 // Show what the original file looks like.
938 {
Lei Zhang0c03d632020-07-30 17:05:36 +0000939#if defined(OS_APPLE)
Lei Zhang0f6b4342020-02-25 20:00:39 +0000940 const char kOriginalMD5[] = "adf815e53c788a5272b4df07c610a1da";
Lei Zhange67bcc72019-04-30 18:55:58 +0000941#elif defined(OS_WIN)
Lei Zhanga2b70732019-06-25 08:34:22 +0000942 const char kOriginalMD5[] = "00542ee435b37749c4453be63bf7bdb6";
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000943#else
Lei Zhanga2b70732019-06-25 08:34:22 +0000944 const char kOriginalMD5[] = "41647268d5911d049801803b15c2dfb0";
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000945#endif
Lei Zhang30ff2532019-01-31 21:37:55 +0000946 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000947 CompareBitmap(page_bitmap.get(), 200, 200, kOriginalMD5);
948 }
949
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000950 constexpr int expected_object_count = 19;
951 CheckMarkCounts(page, 1, expected_object_count, 8, 4, 9, 1);
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000952
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000953 // Get all objects marked with "Prime"
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000954 std::vector<FPDF_PAGEOBJECT> primes;
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000955 for (int i = 0; i < expected_object_count; ++i) {
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000956 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
957
958 int mark_count = FPDFPageObj_CountMarks(page_object);
959 for (int j = 0; j < mark_count; ++j) {
960 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
961
962 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +0000963 unsigned long name_len = 999u;
964 ASSERT_TRUE(
965 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
966 EXPECT_GT(name_len, 0u);
967 EXPECT_NE(999u, name_len);
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000968 std::wstring name =
969 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
970 if (name == L"Prime") {
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000971 primes.push_back(page_object);
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000972 }
973 }
974 }
975
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000976 // Remove all objects marked with "Prime".
977 for (FPDF_PAGEOBJECT page_object : primes) {
978 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
979 FPDFPageObj_Destroy(page_object);
980 }
981
982 EXPECT_EQ(11, FPDFPage_CountObjects(page));
983
Lei Zhang0c03d632020-07-30 17:05:36 +0000984#if defined(OS_APPLE)
Lei Zhang0f6b4342020-02-25 20:00:39 +0000985 const char kNonPrimesMD5[] = "d29e2ddff56e0d12f340794d26796400";
986 const char kNonPrimesAfterSaveMD5[] = "10eff2cd0037b661496981779601fa6f";
Lei Zhange67bcc72019-04-30 18:55:58 +0000987#elif defined(OS_WIN)
Lei Zhanga2b70732019-06-25 08:34:22 +0000988 const char kNonPrimesMD5[] = "86e371fdae30c2471f476631f3f93413";
989 const char kNonPrimesAfterSaveMD5[] = "86e371fdae30c2471f476631f3f93413";
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000990#else
Lei Zhanga2b70732019-06-25 08:34:22 +0000991 const char kNonPrimesMD5[] = "67ab13115d0cc34e99a1003c28047b40";
992 const char kNonPrimesAfterSaveMD5[] = "67ab13115d0cc34e99a1003c28047b40";
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000993#endif
Henrique Nakashimaa5078b72018-09-10 17:09:42 +0000994 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000995 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000996 CompareBitmap(page_bitmap.get(), 200, 200, kNonPrimesMD5);
997 }
998
Henrique Nakashimaa5078b72018-09-10 17:09:42 +0000999 // Save the file.
1000 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1001 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001002 UnloadPage(page);
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001003
1004 // Re-open the file and check the prime marks are not there anymore.
Lei Zhang0b494052019-01-31 21:41:15 +00001005 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001006 FPDF_PAGE saved_page = LoadSavedPage(0);
1007 EXPECT_EQ(11, FPDFPage_CountObjects(saved_page));
1008
1009 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001010 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Manoj Biswas7daf7a22019-03-22 23:02:34 +00001011 CompareBitmap(page_bitmap.get(), 200, 200, kNonPrimesAfterSaveMD5);
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001012 }
1013
1014 CloseSavedPage(saved_page);
1015 CloseSavedDocument();
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001016}
1017
Lei Zhangab41f252018-12-23 03:10:50 +00001018TEST_F(FPDFEditEmbedderTest, RemoveMarks) {
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001019 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001020 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001021 FPDF_PAGE page = LoadPage(0);
1022 ASSERT_TRUE(page);
1023
1024 constexpr int kExpectedObjectCount = 19;
1025 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
1026
1027 // Remove all "Prime" content marks.
1028 for (int i = 0; i < kExpectedObjectCount; ++i) {
1029 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1030
1031 int mark_count = FPDFPageObj_CountMarks(page_object);
1032 for (int j = mark_count - 1; j >= 0; --j) {
1033 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
1034
1035 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001036 unsigned long name_len = 999u;
1037 ASSERT_TRUE(
1038 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
1039 EXPECT_GT(name_len, 0u);
1040 EXPECT_NE(999u, name_len);
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001041 std::wstring name =
1042 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1043 if (name == L"Prime") {
1044 // Remove mark.
1045 EXPECT_TRUE(FPDFPageObj_RemoveMark(page_object, mark));
1046
1047 // Verify there is now one fewer mark in the page object.
1048 EXPECT_EQ(mark_count - 1, FPDFPageObj_CountMarks(page_object));
1049 }
1050 }
1051 }
1052
1053 // Verify there are 0 "Prime" content marks now.
1054 CheckMarkCounts(page, 1, kExpectedObjectCount, 0, 4, 9, 1);
1055
1056 // Save the file.
1057 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1058 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1059 UnloadPage(page);
1060
1061 // Re-open the file and check the prime marks are not there anymore.
Lei Zhang0b494052019-01-31 21:41:15 +00001062 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001063 FPDF_PAGE saved_page = LoadSavedPage(0);
1064
1065 CheckMarkCounts(saved_page, 1, kExpectedObjectCount, 0, 4, 9, 1);
1066
1067 CloseSavedPage(saved_page);
1068 CloseSavedDocument();
1069}
1070
Lei Zhangab41f252018-12-23 03:10:50 +00001071TEST_F(FPDFEditEmbedderTest, RemoveMarkParam) {
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001072 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001073 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001074 FPDF_PAGE page = LoadPage(0);
1075 ASSERT_TRUE(page);
1076
1077 constexpr int kExpectedObjectCount = 19;
1078 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
1079
1080 // Remove all "Square" content marks parameters.
1081 for (int i = 0; i < kExpectedObjectCount; ++i) {
1082 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1083
1084 int mark_count = FPDFPageObj_CountMarks(page_object);
1085 for (int j = 0; j < mark_count; ++j) {
1086 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
1087
1088 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001089 unsigned long name_len = 999u;
1090 ASSERT_TRUE(
1091 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
1092 EXPECT_GT(name_len, 0u);
1093 EXPECT_NE(999u, name_len);
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001094 std::wstring name =
1095 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1096 if (name == L"Square") {
1097 // Show the mark has a "Factor" parameter.
1098 int out_value;
1099 EXPECT_TRUE(
1100 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
1101
1102 // Remove parameter.
1103 EXPECT_TRUE(FPDFPageObjMark_RemoveParam(page_object, mark, "Factor"));
1104
1105 // Verify the "Factor" parameter is gone.
1106 EXPECT_FALSE(
1107 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
1108 }
1109 }
1110 }
1111
1112 // Save the file.
1113 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1114 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1115 UnloadPage(page);
1116
1117 // Re-open the file and check the "Factor" parameters are still gone.
Lei Zhang0b494052019-01-31 21:41:15 +00001118 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001119 FPDF_PAGE saved_page = LoadSavedPage(0);
1120
1121 size_t square_count = 0;
1122 for (int i = 0; i < kExpectedObjectCount; ++i) {
1123 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(saved_page, i);
1124
1125 int mark_count = FPDFPageObj_CountMarks(page_object);
1126 for (int j = 0; j < mark_count; ++j) {
1127 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
1128
1129 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001130 unsigned long name_len = 999u;
1131 ASSERT_TRUE(
1132 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
1133 EXPECT_GT(name_len, 0u);
1134 EXPECT_NE(999u, name_len);
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001135 std::wstring name =
1136 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1137 if (name == L"Square") {
1138 // Verify the "Factor" parameter is still gone.
1139 int out_value;
1140 EXPECT_FALSE(
1141 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
1142
1143 ++square_count;
1144 }
1145 }
1146 }
1147
1148 // Verify the parameters are gone, but the marks are not.
1149 EXPECT_EQ(4u, square_count);
1150
1151 CloseSavedPage(saved_page);
1152 CloseSavedDocument();
1153}
1154
Lei Zhangab41f252018-12-23 03:10:50 +00001155TEST_F(FPDFEditEmbedderTest, MaintainMarkedObjects) {
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001156 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001157 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001158 FPDF_PAGE page = LoadPage(0);
1159 ASSERT_TRUE(page);
1160
1161 // Iterate over all objects, counting the number of times each content mark
1162 // name appears.
1163 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
1164
1165 // Remove first page object.
1166 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1167 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1168 FPDFPageObj_Destroy(page_object);
1169
1170 CheckMarkCounts(page, 2, 18, 8, 3, 9, 1);
1171
1172 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1173 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1174
1175 UnloadPage(page);
1176
Lei Zhang0b494052019-01-31 21:41:15 +00001177 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001178 FPDF_PAGE saved_page = LoadSavedPage(0);
1179
1180 CheckMarkCounts(saved_page, 2, 18, 8, 3, 9, 1);
1181
1182 CloseSavedPage(saved_page);
1183 CloseSavedDocument();
1184}
1185
Lei Zhangab41f252018-12-23 03:10:50 +00001186TEST_F(FPDFEditEmbedderTest, MaintainIndirectMarkedObjects) {
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001187 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001188 ASSERT_TRUE(OpenDocument("text_in_page_marked_indirect.pdf"));
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001189 FPDF_PAGE page = LoadPage(0);
1190 ASSERT_TRUE(page);
1191
1192 // Iterate over all objects, counting the number of times each content mark
1193 // name appears.
1194 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
1195
1196 // Remove first page object.
1197 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1198 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1199 FPDFPageObj_Destroy(page_object);
1200
1201 CheckMarkCounts(page, 2, 18, 8, 3, 9, 1);
1202
1203 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1204 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1205
1206 UnloadPage(page);
1207
Lei Zhang0b494052019-01-31 21:41:15 +00001208 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001209 FPDF_PAGE saved_page = LoadSavedPage(0);
1210
1211 CheckMarkCounts(saved_page, 2, 18, 8, 3, 9, 1);
1212
1213 CloseSavedPage(saved_page);
1214 CloseSavedDocument();
1215}
1216
Lei Zhangab41f252018-12-23 03:10:50 +00001217TEST_F(FPDFEditEmbedderTest, RemoveExistingPageObject) {
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001218 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001219 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001220 FPDF_PAGE page = LoadPage(0);
1221 ASSERT_TRUE(page);
1222
1223 // Get the "Hello, world!" text object and remove it.
1224 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1225 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1226 ASSERT_TRUE(page_object);
1227 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1228
1229 // Verify the "Hello, world!" text is gone.
1230 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1231
1232 // Save the file
1233 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1234 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1235 UnloadPage(page);
1236 FPDFPageObj_Destroy(page_object);
1237
1238 // Re-open the file and check the page object count is still 1.
Lei Zhang0b494052019-01-31 21:41:15 +00001239 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001240 FPDF_PAGE saved_page = LoadSavedPage(0);
1241 EXPECT_EQ(1, FPDFPage_CountObjects(saved_page));
1242 CloseSavedPage(saved_page);
1243 CloseSavedDocument();
1244}
1245
Hui Yingstcb4203d2020-06-09 01:48:47 +00001246TEST_F(FPDFEditEmbedderTest, RemoveExistingPageObjectSplitStreamsNotLonely) {
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001247 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001248 ASSERT_TRUE(OpenDocument("hello_world_split_streams.pdf"));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001249 FPDF_PAGE page = LoadPage(0);
1250 ASSERT_TRUE(page);
1251
1252 // Get the "Hello, world!" text object and remove it. There is another object
1253 // in the same stream that says "Goodbye, world!"
1254 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1255 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1256 ASSERT_TRUE(page_object);
1257 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1258
1259 // Verify the "Hello, world!" text is gone.
1260 ASSERT_EQ(2, FPDFPage_CountObjects(page));
Hui Yingstcb4203d2020-06-09 01:48:47 +00001261#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1262#if defined(OS_WIN)
1263 const char kHelloRemovedChecksum[] = "e05c7837a5cad61305d157720637f969";
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001264#else
Hui Yingstcb4203d2020-06-09 01:48:47 +00001265 const char kHelloRemovedChecksum[] = "deed7dc2754dc80930f3b05e2ac86c94";
1266#endif // defined(OS_WIN)
1267#else
1268#if defined(OS_WIN)
1269 const char kHelloRemovedChecksum[] = "a97d4c72c969ba373c2dce675d277e65";
Lei Zhang0c03d632020-07-30 17:05:36 +00001270#elif defined(OS_APPLE)
Hui Yingstcb4203d2020-06-09 01:48:47 +00001271 const char kHelloRemovedChecksum[] = "3b3b27602a86dfe5996a33c42c59885b";
1272#else
1273 const char kHelloRemovedChecksum[] = "95b92950647a2190e1230911e7a1a0e9";
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001274#endif
Hui Yingstcb4203d2020-06-09 01:48:47 +00001275#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001276 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001277 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstcb4203d2020-06-09 01:48:47 +00001278 CompareBitmap(page_bitmap.get(), 200, 200, kHelloRemovedChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001279 }
1280
1281 // Save the file
1282 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1283 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1284 UnloadPage(page);
1285 FPDFPageObj_Destroy(page_object);
1286
1287 // Re-open the file and check the page object count is still 2.
Lei Zhang0b494052019-01-31 21:41:15 +00001288 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001289 FPDF_PAGE saved_page = LoadSavedPage(0);
1290
1291 EXPECT_EQ(2, FPDFPage_CountObjects(saved_page));
1292 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001293 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstcb4203d2020-06-09 01:48:47 +00001294 CompareBitmap(page_bitmap.get(), 200, 200, kHelloRemovedChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001295 }
1296
1297 CloseSavedPage(saved_page);
1298 CloseSavedDocument();
1299}
1300
Hui Yingst08c40712020-04-29 01:37:35 +00001301TEST_F(FPDFEditEmbedderTest, RemoveExistingPageObjectSplitStreamsLonely) {
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001302 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001303 ASSERT_TRUE(OpenDocument("hello_world_split_streams.pdf"));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001304 FPDF_PAGE page = LoadPage(0);
1305 ASSERT_TRUE(page);
1306
1307 // Get the "Greetings, world!" text object and remove it. This is the only
1308 // object in the stream.
1309 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1310 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 2);
1311 ASSERT_TRUE(page_object);
1312 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1313
1314 // Verify the "Greetings, world!" text is gone.
1315 ASSERT_EQ(2, FPDFPage_CountObjects(page));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001316 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001317 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001318 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001319 }
1320
1321 // Save the file
1322 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1323 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1324 UnloadPage(page);
1325 FPDFPageObj_Destroy(page_object);
1326
1327 // Re-open the file and check the page object count is still 2.
Lei Zhang0b494052019-01-31 21:41:15 +00001328 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001329 FPDF_PAGE saved_page = LoadSavedPage(0);
1330
1331 EXPECT_EQ(2, FPDFPage_CountObjects(saved_page));
1332 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001333 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001334 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001335 }
1336
1337 CloseSavedPage(saved_page);
1338 CloseSavedDocument();
1339}
1340
Lei Zhangab41f252018-12-23 03:10:50 +00001341TEST_F(FPDFEditEmbedderTest, GetContentStream) {
Henrique Nakashima6eb79392018-06-12 20:27:35 +00001342 // Load document with some text split across streams.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001343 ASSERT_TRUE(OpenDocument("split_streams.pdf"));
Henrique Nakashima6eb79392018-06-12 20:27:35 +00001344 FPDF_PAGE page = LoadPage(0);
1345 ASSERT_TRUE(page);
1346
1347 // Content stream 0: page objects 0-14.
1348 // Content stream 1: page objects 15-17.
1349 // Content stream 2: page object 18.
1350 ASSERT_EQ(19, FPDFPage_CountObjects(page));
1351 for (int i = 0; i < 19; i++) {
1352 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1353 ASSERT_TRUE(page_object);
1354 CPDF_PageObject* cpdf_page_object =
1355 CPDFPageObjectFromFPDFPageObject(page_object);
1356 if (i < 15)
1357 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1358 else if (i < 18)
1359 EXPECT_EQ(1, cpdf_page_object->GetContentStream()) << i;
1360 else
1361 EXPECT_EQ(2, cpdf_page_object->GetContentStream()) << i;
1362 }
1363
1364 UnloadPage(page);
1365}
1366
Lei Zhang03e5e682019-09-16 19:45:55 +00001367// TODO(crbug.com/pdfium/11): Fix this test and enable.
1368#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1369#define MAYBE_RemoveAllFromStream DISABLED_RemoveAllFromStream
1370#else
1371#define MAYBE_RemoveAllFromStream RemoveAllFromStream
1372#endif
1373TEST_F(FPDFEditEmbedderTest, MAYBE_RemoveAllFromStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001374 // Load document with some text split across streams.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001375 ASSERT_TRUE(OpenDocument("split_streams.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001376 FPDF_PAGE page = LoadPage(0);
1377 ASSERT_TRUE(page);
1378
1379 // Content stream 0: page objects 0-14.
1380 // Content stream 1: page objects 15-17.
1381 // Content stream 2: page object 18.
1382 ASSERT_EQ(19, FPDFPage_CountObjects(page));
1383
1384 // Loop backwards because objects will being removed, which shifts the indexes
1385 // after the removed position.
1386 for (int i = 18; i >= 0; i--) {
1387 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1388 ASSERT_TRUE(page_object);
1389 CPDF_PageObject* cpdf_page_object =
1390 CPDFPageObjectFromFPDFPageObject(page_object);
1391
1392 // Empty content stream 1.
1393 if (cpdf_page_object->GetContentStream() == 1) {
1394 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1395 FPDFPageObj_Destroy(page_object);
1396 }
1397 }
1398
1399 // Content stream 0: page objects 0-14.
1400 // Content stream 2: page object 15.
1401 ASSERT_EQ(16, FPDFPage_CountObjects(page));
1402 for (int i = 0; i < 16; i++) {
1403 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1404 ASSERT_TRUE(page_object);
1405 CPDF_PageObject* cpdf_page_object =
1406 CPDFPageObjectFromFPDFPageObject(page_object);
1407 if (i < 15)
1408 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1409 else
1410 EXPECT_EQ(2, cpdf_page_object->GetContentStream()) << i;
1411 }
1412
1413 // Generate contents should remove the empty stream and update the page
1414 // objects' contents stream indexes.
1415 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1416
1417 // Content stream 0: page objects 0-14.
1418 // Content stream 1: page object 15.
1419 ASSERT_EQ(16, FPDFPage_CountObjects(page));
1420 for (int i = 0; i < 16; i++) {
1421 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1422 ASSERT_TRUE(page_object);
1423 CPDF_PageObject* cpdf_page_object =
1424 CPDFPageObjectFromFPDFPageObject(page_object);
1425 if (i < 15)
1426 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1427 else
1428 EXPECT_EQ(1, cpdf_page_object->GetContentStream()) << i;
1429 }
1430
Lei Zhang0c03d632020-07-30 17:05:36 +00001431#if defined(OS_APPLE)
Lei Zhang0f6b4342020-02-25 20:00:39 +00001432 const char kStream1RemovedMD5[] = "0e8856ca9abc7049412e64f9230c7c43";
Lei Zhange67bcc72019-04-30 18:55:58 +00001433#elif defined(OS_WIN)
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001434 const char kStream1RemovedMD5[] = "b4140f203523e38793283a5943d8075b";
1435#else
1436 const char kStream1RemovedMD5[] = "e86a3efc160ede6cfcb1f59bcacf1105";
1437#endif
1438 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001439 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001440 CompareBitmap(page_bitmap.get(), 200, 200, kStream1RemovedMD5);
1441 }
1442
1443 // Save the file
1444 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1445 UnloadPage(page);
1446
1447 // Re-open the file and check the page object count is still 16, and that
1448 // content stream 1 was removed.
Lei Zhang0b494052019-01-31 21:41:15 +00001449 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001450 FPDF_PAGE saved_page = LoadSavedPage(0);
1451
1452 // Content stream 0: page objects 0-14.
1453 // Content stream 1: page object 15.
1454 EXPECT_EQ(16, FPDFPage_CountObjects(saved_page));
1455 for (int i = 0; i < 16; i++) {
1456 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(saved_page, i);
1457 ASSERT_TRUE(page_object);
1458 CPDF_PageObject* cpdf_page_object =
1459 CPDFPageObjectFromFPDFPageObject(page_object);
1460 if (i < 15)
1461 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1462 else
1463 EXPECT_EQ(1, cpdf_page_object->GetContentStream()) << i;
1464 }
1465
1466 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001467 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001468 CompareBitmap(page_bitmap.get(), 200, 200, kStream1RemovedMD5);
1469 }
1470
1471 CloseSavedPage(saved_page);
1472 CloseSavedDocument();
1473}
1474
Lei Zhangab41f252018-12-23 03:10:50 +00001475TEST_F(FPDFEditEmbedderTest, RemoveAllFromSingleStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001476 // Load document with a single stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001477 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001478 FPDF_PAGE page = LoadPage(0);
1479 ASSERT_TRUE(page);
1480
1481 // Content stream 0: page objects 0-1.
1482 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1483
1484 // Loop backwards because objects will being removed, which shifts the indexes
1485 // after the removed position.
1486 for (int i = 1; i >= 0; i--) {
1487 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1488 ASSERT_TRUE(page_object);
1489 CPDF_PageObject* cpdf_page_object =
1490 CPDFPageObjectFromFPDFPageObject(page_object);
1491 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1492 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1493 FPDFPageObj_Destroy(page_object);
1494 }
1495
1496 // No more objects in the stream
1497 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1498
1499 // Generate contents should remove the empty stream and update the page
1500 // objects' contents stream indexes.
1501 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1502
1503 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1504
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001505 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001506 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001507 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001508 }
1509
1510 // Save the file
1511 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1512 UnloadPage(page);
1513
1514 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001515 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001516 FPDF_PAGE saved_page = LoadSavedPage(0);
1517
1518 EXPECT_EQ(0, FPDFPage_CountObjects(saved_page));
1519 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001520 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001521 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001522 }
1523
1524 CloseSavedPage(saved_page);
1525 CloseSavedDocument();
1526}
1527
Hui Yingst08c40712020-04-29 01:37:35 +00001528TEST_F(FPDFEditEmbedderTest, RemoveFirstFromSingleStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001529 // Load document with a single stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001530 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001531 FPDF_PAGE page = LoadPage(0);
1532 ASSERT_TRUE(page);
1533
1534 // Content stream 0: page objects 0-1.
1535 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1536
1537 // Remove first object.
1538 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1539 ASSERT_TRUE(page_object);
1540 CPDF_PageObject* cpdf_page_object =
1541 CPDFPageObjectFromFPDFPageObject(page_object);
1542 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1543 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1544 FPDFPageObj_Destroy(page_object);
1545
1546 // One object left in the stream.
1547 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1548 page_object = FPDFPage_GetObject(page, 0);
1549 ASSERT_TRUE(page_object);
1550 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1551 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1552
1553 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1554
1555 // Still one object left in the stream.
1556 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1557 page_object = FPDFPage_GetObject(page, 0);
1558 ASSERT_TRUE(page_object);
1559 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1560 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1561
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001562 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001563 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001564 CompareBitmap(page_bitmap.get(), 200, 200, kFirstRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001565 }
1566
1567 // Save the file
1568 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1569 UnloadPage(page);
1570
1571 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001572 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001573 FPDF_PAGE saved_page = LoadSavedPage(0);
1574
1575 ASSERT_EQ(1, FPDFPage_CountObjects(saved_page));
1576 page_object = FPDFPage_GetObject(saved_page, 0);
1577 ASSERT_TRUE(page_object);
1578 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1579 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1580 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001581 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001582 CompareBitmap(page_bitmap.get(), 200, 200, kFirstRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001583 }
1584
1585 CloseSavedPage(saved_page);
1586 CloseSavedDocument();
1587}
1588
Hui Yingst08c40712020-04-29 01:37:35 +00001589TEST_F(FPDFEditEmbedderTest, RemoveLastFromSingleStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001590 // Load document with a single stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001591 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001592 FPDF_PAGE page = LoadPage(0);
1593 ASSERT_TRUE(page);
1594
1595 // Content stream 0: page objects 0-1.
1596 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1597
1598 // Remove last object
1599 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 1);
1600 ASSERT_TRUE(page_object);
1601 CPDF_PageObject* cpdf_page_object =
1602 CPDFPageObjectFromFPDFPageObject(page_object);
1603 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1604 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1605 FPDFPageObj_Destroy(page_object);
1606
1607 // One object left in the stream.
1608 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1609 page_object = FPDFPage_GetObject(page, 0);
1610 ASSERT_TRUE(page_object);
1611 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1612 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1613
1614 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1615
1616 // Still one object left in the stream.
1617 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1618 page_object = FPDFPage_GetObject(page, 0);
1619 ASSERT_TRUE(page_object);
1620 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1621 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1622
Hui Yingstb4baceb2020-04-28 23:46:10 +00001623 using pdfium::kHelloWorldRemovedChecksum;
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001624 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001625 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001626 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001627 }
1628
1629 // Save the file
1630 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1631 UnloadPage(page);
1632
1633 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001634 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001635 FPDF_PAGE saved_page = LoadSavedPage(0);
1636
1637 ASSERT_EQ(1, FPDFPage_CountObjects(saved_page));
1638 page_object = FPDFPage_GetObject(saved_page, 0);
1639 ASSERT_TRUE(page_object);
1640 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1641 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1642 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001643 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001644 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001645 }
1646
1647 CloseSavedPage(saved_page);
1648 CloseSavedDocument();
1649}
1650
Lei Zhangab41f252018-12-23 03:10:50 +00001651TEST_F(FPDFEditEmbedderTest, RemoveAllFromMultipleStreams) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001652 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001653 ASSERT_TRUE(OpenDocument("hello_world_split_streams.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001654 FPDF_PAGE page = LoadPage(0);
1655 ASSERT_TRUE(page);
1656
1657 // Content stream 0: page objects 0-1.
1658 // Content stream 1: page object 2.
1659 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1660
1661 // Loop backwards because objects will being removed, which shifts the indexes
1662 // after the removed position.
1663 for (int i = 2; i >= 0; i--) {
1664 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1665 ASSERT_TRUE(page_object);
1666 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1667 FPDFPageObj_Destroy(page_object);
1668 }
1669
1670 // No more objects in the page.
1671 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1672
1673 // Generate contents should remove the empty streams and update the page
1674 // objects' contents stream indexes.
1675 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1676
1677 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1678
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001679 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001680 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001681 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001682 }
1683
1684 // Save the file
1685 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1686 UnloadPage(page);
1687
1688 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001689 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001690 FPDF_PAGE saved_page = LoadSavedPage(0);
1691
1692 EXPECT_EQ(0, FPDFPage_CountObjects(saved_page));
1693 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001694 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001695 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001696 }
1697
1698 CloseSavedPage(saved_page);
1699 CloseSavedDocument();
1700}
1701
Lei Zhangab41f252018-12-23 03:10:50 +00001702TEST_F(FPDFEditEmbedderTest, InsertPageObjectAndSave) {
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001703 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001704 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001705 FPDF_PAGE page = LoadPage(0);
1706 ASSERT_TRUE(page);
1707
1708 // Add a red rectangle.
1709 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1710 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001711 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001712 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
1713 FPDFPage_InsertObject(page, red_rect);
1714
1715 // Verify the red rectangle was added.
1716 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1717
1718 // Save the file
1719 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1720 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1721 UnloadPage(page);
1722
1723 // Re-open the file and check the page object count is still 3.
Lei Zhang0b494052019-01-31 21:41:15 +00001724 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001725 FPDF_PAGE saved_page = LoadSavedPage(0);
1726 EXPECT_EQ(3, FPDFPage_CountObjects(saved_page));
1727 CloseSavedPage(saved_page);
1728 CloseSavedDocument();
1729}
1730
Lei Zhangab41f252018-12-23 03:10:50 +00001731TEST_F(FPDFEditEmbedderTest, InsertPageObjectEditAndSave) {
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001732 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001733 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001734 FPDF_PAGE page = LoadPage(0);
1735 ASSERT_TRUE(page);
1736
1737 // Add a red rectangle.
1738 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1739 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001740 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 100, 100, 255));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001741 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
1742 FPDFPage_InsertObject(page, red_rect);
1743
1744 // Verify the red rectangle was added.
1745 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1746
1747 // Generate content but change it again
1748 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhang3475b482019-05-13 18:30:57 +00001749 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001750
1751 // Save the file
1752 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1753 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1754 UnloadPage(page);
1755
1756 // Re-open the file and check the page object count is still 3.
Lei Zhang0b494052019-01-31 21:41:15 +00001757 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001758 FPDF_PAGE saved_page = LoadSavedPage(0);
1759 EXPECT_EQ(3, FPDFPage_CountObjects(saved_page));
1760 CloseSavedPage(saved_page);
1761 CloseSavedDocument();
1762}
1763
Hui Yingst8b5dfb22020-07-21 17:08:30 +00001764TEST_F(FPDFEditEmbedderTest, InsertAndRemoveLargeFile) {
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001765 const int kOriginalObjectCount = 600;
1766
1767 // Load document with many objects.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001768 ASSERT_TRUE(OpenDocument("many_rectangles.pdf"));
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001769 FPDF_PAGE page = LoadPage(0);
1770 ASSERT_TRUE(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001771
1772 using pdfium::kManyRectanglesChecksum;
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001773 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001774 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001775 CompareBitmap(page_bitmap.get(), 200, 300, kManyRectanglesChecksum);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001776 }
1777
1778 // Add a black rectangle.
1779 ASSERT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(page));
1780 FPDF_PAGEOBJECT black_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001781 EXPECT_TRUE(FPDFPageObj_SetFillColor(black_rect, 0, 0, 0, 255));
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001782 EXPECT_TRUE(FPDFPath_SetDrawMode(black_rect, FPDF_FILLMODE_ALTERNATE, 0));
1783 FPDFPage_InsertObject(page, black_rect);
1784
1785 // Verify the black rectangle was added.
1786 ASSERT_EQ(kOriginalObjectCount + 1, FPDFPage_CountObjects(page));
Hui Yingst8b5dfb22020-07-21 17:08:30 +00001787#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1788 const char kPlusRectangleMD5[] = "0d3715fcfb9bd0dd25dcce60800bff47";
1789#else
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001790 const char kPlusRectangleMD5[] = "6b9396ab570754b32b04ca629e902f77";
Hui Yingst8b5dfb22020-07-21 17:08:30 +00001791#endif
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001792 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001793 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001794 CompareBitmap(page_bitmap.get(), 200, 300, kPlusRectangleMD5);
1795 }
1796
1797 // Save the file.
1798 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1799 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1800 UnloadPage(page);
1801
1802 // Re-open the file and check the rectangle added is still there.
Lei Zhang0b494052019-01-31 21:41:15 +00001803 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001804 FPDF_PAGE saved_page = LoadSavedPage(0);
1805 EXPECT_EQ(kOriginalObjectCount + 1, FPDFPage_CountObjects(saved_page));
1806 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001807 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001808 CompareBitmap(page_bitmap.get(), 200, 300, kPlusRectangleMD5);
1809 }
1810
1811 // Remove the added rectangle.
1812 FPDF_PAGEOBJECT added_object =
1813 FPDFPage_GetObject(saved_page, kOriginalObjectCount);
1814 EXPECT_TRUE(FPDFPage_RemoveObject(saved_page, added_object));
1815 FPDFPageObj_Destroy(added_object);
1816 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001817 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001818 CompareBitmap(page_bitmap.get(), 200, 300, kManyRectanglesChecksum);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001819 }
1820 EXPECT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(saved_page));
1821
1822 // Save the file again.
1823 EXPECT_TRUE(FPDFPage_GenerateContent(saved_page));
1824 EXPECT_TRUE(FPDF_SaveAsCopy(saved_document_, this, 0));
1825
1826 CloseSavedPage(saved_page);
1827 CloseSavedDocument();
1828
1829 // Re-open the file (again) and check the black rectangle was removed and the
1830 // rest is intact.
Lei Zhang0b494052019-01-31 21:41:15 +00001831 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001832 saved_page = LoadSavedPage(0);
1833 EXPECT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(saved_page));
1834 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001835 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001836 CompareBitmap(page_bitmap.get(), 200, 300, kManyRectanglesChecksum);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001837 }
1838
1839 CloseSavedPage(saved_page);
1840 CloseSavedDocument();
1841}
1842
Lei Zhangab41f252018-12-23 03:10:50 +00001843TEST_F(FPDFEditEmbedderTest, AddAndRemovePaths) {
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001844 // Start with a blank page.
1845 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
1846 ASSERT_TRUE(page);
1847
1848 // Render the blank page and verify it's a blank bitmap.
Hui Yingstb4baceb2020-04-28 23:46:10 +00001849 using pdfium::kBlankPage612By792Checksum;
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001850 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001851 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001852 CompareBitmap(page_bitmap.get(), 612, 792, kBlankPage612By792Checksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001853 }
1854 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1855
1856 // Add a red rectangle.
1857 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
1858 ASSERT_TRUE(red_rect);
Lei Zhang3475b482019-05-13 18:30:57 +00001859 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001860 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
1861 FPDFPage_InsertObject(page, red_rect);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001862 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001863 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001864 CompareBitmap(page_bitmap.get(), 612, 792, kRedRectangleChecksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001865 }
1866 EXPECT_EQ(1, FPDFPage_CountObjects(page));
1867
1868 // Remove rectangle and verify it does not render anymore and the bitmap is
1869 // back to a blank one.
1870 EXPECT_TRUE(FPDFPage_RemoveObject(page, red_rect));
1871 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001872 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001873 CompareBitmap(page_bitmap.get(), 612, 792, kBlankPage612By792Checksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001874 }
1875 EXPECT_EQ(0, FPDFPage_CountObjects(page));
1876
1877 // Trying to remove an object not in the page should return false.
1878 EXPECT_FALSE(FPDFPage_RemoveObject(page, red_rect));
1879
1880 FPDF_ClosePage(page);
1881 FPDFPageObj_Destroy(red_rect);
1882}
1883
Lei Zhangab41f252018-12-23 03:10:50 +00001884TEST_F(FPDFEditEmbedderTest, PathsPoints) {
Miklos Vajna12abfd02017-09-15 07:49:03 +02001885 CreateNewDocument();
1886 FPDF_PAGEOBJECT img = FPDFPageObj_NewImageObj(document_);
1887 // This should fail gracefully, even if img is not a path.
Miklos Vajna0150a542017-09-21 21:46:56 +02001888 ASSERT_EQ(-1, FPDFPath_CountSegments(img));
Miklos Vajna12abfd02017-09-15 07:49:03 +02001889
1890 // This should fail gracefully, even if path is NULL.
Miklos Vajna0150a542017-09-21 21:46:56 +02001891 ASSERT_EQ(-1, FPDFPath_CountSegments(nullptr));
Miklos Vajna12abfd02017-09-15 07:49:03 +02001892
Miklos Vajna36eed872017-09-20 22:52:43 +02001893 // FPDFPath_GetPathSegment() with a non-path.
1894 ASSERT_EQ(nullptr, FPDFPath_GetPathSegment(img, 0));
1895 // FPDFPath_GetPathSegment() with a NULL path.
1896 ASSERT_EQ(nullptr, FPDFPath_GetPathSegment(nullptr, 0));
1897 float x;
1898 float y;
1899 // FPDFPathSegment_GetPoint() with a NULL segment.
1900 EXPECT_FALSE(FPDFPathSegment_GetPoint(nullptr, &x, &y));
1901
1902 // FPDFPathSegment_GetType() with a NULL segment.
1903 ASSERT_EQ(FPDF_SEGMENT_UNKNOWN, FPDFPathSegment_GetType(nullptr));
1904
1905 // FPDFPathSegment_GetClose() with a NULL segment.
1906 EXPECT_FALSE(FPDFPathSegment_GetClose(nullptr));
1907
Miklos Vajna12abfd02017-09-15 07:49:03 +02001908 FPDFPageObj_Destroy(img);
1909}
1910
Hui Yingste95d5772020-08-24 23:58:26 +00001911TEST_F(FPDFEditEmbedderTest, PathOnTopOfText) {
Nicolas Pena0fc185e2017-02-08 12:13:20 -05001912 // Load document with some text
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001913 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Nicolas Pena0fc185e2017-02-08 12:13:20 -05001914 FPDF_PAGE page = LoadPage(0);
Lei Zhang107fa7b2018-02-09 21:48:15 +00001915 ASSERT_TRUE(page);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05001916
1917 // Add an opaque rectangle on top of some of the text.
1918 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001919 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Nicolas Pena0fc185e2017-02-08 12:13:20 -05001920 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
1921 FPDFPage_InsertObject(page, red_rect);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05001922
1923 // Add a transparent triangle on top of other part of the text.
1924 FPDF_PAGEOBJECT black_path = FPDFPageObj_CreateNewPath(20, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001925 EXPECT_TRUE(FPDFPageObj_SetFillColor(black_path, 0, 0, 0, 100));
Nicolas Pena0fc185e2017-02-08 12:13:20 -05001926 EXPECT_TRUE(FPDFPath_SetDrawMode(black_path, FPDF_FILLMODE_ALTERNATE, 0));
1927 EXPECT_TRUE(FPDFPath_LineTo(black_path, 30, 80));
1928 EXPECT_TRUE(FPDFPath_LineTo(black_path, 40, 10));
1929 EXPECT_TRUE(FPDFPath_Close(black_path));
1930 FPDFPage_InsertObject(page, black_path);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05001931
Hui Yingste95d5772020-08-24 23:58:26 +00001932 // Render and check the result.
Tom Sepeze08d2b12018-04-25 18:49:32 +00001933 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
Hui Yingste95d5772020-08-24 23:58:26 +00001934#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1935#if defined(OS_WIN)
1936 const char kChecksum[] = "e755a955696373e39dbebb5cb96e1338";
Nicolas Pena0fc185e2017-02-08 12:13:20 -05001937#else
Hui Yingste95d5772020-08-24 23:58:26 +00001938 const char kChecksum[] = "d082f9756c86bb47e1abbc2b1df7138a";
1939#endif // defined(OS_WIN)
1940#else
1941#if defined(OS_WIN)
1942 const char kChecksum[] = "74dd9c393b8b2578d2b7feb032b7daad";
1943#elif defined(OS_APPLE)
1944 const char kChecksum[] = "e55bcd1facb7243dc6e16dd5f912265b";
1945#else
1946 const char kChecksum[] = "aa71b09b93b55f467f1290e5111babee";
Nicolas Pena5bcd9a32017-03-22 11:04:35 -04001947#endif
Hui Yingste95d5772020-08-24 23:58:26 +00001948#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1949 CompareBitmap(bitmap.get(), 200, 200, kChecksum);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05001950 UnloadPage(page);
1951}
Nicolas Pena2eb1a702017-02-09 18:17:33 -05001952
Hui Yingst1f73c4f2020-07-29 00:46:25 +00001953TEST_F(FPDFEditEmbedderTest, EditOverExistingContent) {
wileyryae858aa42017-05-31 14:49:05 -05001954 // Load document with existing content
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001955 ASSERT_TRUE(OpenDocument("bug_717.pdf"));
wileyryae858aa42017-05-31 14:49:05 -05001956 FPDF_PAGE page = LoadPage(0);
Lei Zhang107fa7b2018-02-09 21:48:15 +00001957 ASSERT_TRUE(page);
wileyryae858aa42017-05-31 14:49:05 -05001958
1959 // Add a transparent rectangle on top of the existing content
1960 FPDF_PAGEOBJECT red_rect2 = FPDFPageObj_CreateNewRect(90, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001961 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect2, 255, 0, 0, 100));
wileyryae858aa42017-05-31 14:49:05 -05001962 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect2, FPDF_FILLMODE_ALTERNATE, 0));
1963 FPDFPage_InsertObject(page, red_rect2);
1964
1965 // Add an opaque rectangle on top of the existing content
1966 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(115, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001967 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
wileyryae858aa42017-05-31 14:49:05 -05001968 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
1969 FPDFPage_InsertObject(page, red_rect);
1970
Hui Yingst1f73c4f2020-07-29 00:46:25 +00001971#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1972 const char kOriginalChecksum[] = "1e82fbdd21490cee9d3479fe6125af67";
1973#else
1974 const char kOriginalChecksum[] = "ad04e5bd0f471a9a564fb034bd0fb073";
1975#endif
Tom Sepeze08d2b12018-04-25 18:49:32 +00001976 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00001977 CompareBitmap(bitmap.get(), 612, 792, kOriginalChecksum);
wileyryae858aa42017-05-31 14:49:05 -05001978 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1979
1980 // Now save the result, closing the page and document
1981 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Nicolas Pena3ff54002017-07-05 11:55:35 -04001982 UnloadPage(page);
wileyryae858aa42017-05-31 14:49:05 -05001983
Lei Zhang0b494052019-01-31 21:41:15 +00001984 ASSERT_TRUE(OpenSavedDocument());
Lei Zhang107fa7b2018-02-09 21:48:15 +00001985 FPDF_PAGE saved_page = LoadSavedPage(0);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00001986 VerifySavedRendering(saved_page, 612, 792, kOriginalChecksum);
wileyryae858aa42017-05-31 14:49:05 -05001987
1988 ClearString();
1989 // Add another opaque rectangle on top of the existing content
1990 FPDF_PAGEOBJECT green_rect = FPDFPageObj_CreateNewRect(150, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001991 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_rect, 0, 255, 0, 255));
wileyryae858aa42017-05-31 14:49:05 -05001992 EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect, FPDF_FILLMODE_ALTERNATE, 0));
Lei Zhang107fa7b2018-02-09 21:48:15 +00001993 FPDFPage_InsertObject(saved_page, green_rect);
wileyryae858aa42017-05-31 14:49:05 -05001994
1995 // Add another transparent rectangle on top of existing content
1996 FPDF_PAGEOBJECT green_rect2 = FPDFPageObj_CreateNewRect(175, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001997 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_rect2, 0, 255, 0, 100));
wileyryae858aa42017-05-31 14:49:05 -05001998 EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect2, FPDF_FILLMODE_ALTERNATE, 0));
Lei Zhang107fa7b2018-02-09 21:48:15 +00001999 FPDFPage_InsertObject(saved_page, green_rect2);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002000#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2001 const char kLastChecksum[] = "8705d023e5fec3499d1e30cf2bcc5dc1";
2002#else
2003 const char kLastChecksum[] = "4b5b00f824620f8c9b8801ebb98e1cdd";
2004#endif
Lei Zhangc113c7a2018-02-12 14:58:44 +00002005 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00002006 ScopedFPDFBitmap new_bitmap = RenderSavedPage(saved_page);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002007 CompareBitmap(new_bitmap.get(), 612, 792, kLastChecksum);
Lei Zhangc113c7a2018-02-12 14:58:44 +00002008 }
Lei Zhang107fa7b2018-02-09 21:48:15 +00002009 EXPECT_TRUE(FPDFPage_GenerateContent(saved_page));
wileyryae858aa42017-05-31 14:49:05 -05002010
2011 // Now save the result, closing the page and document
Lei Zhang0729be22018-02-05 21:13:51 +00002012 EXPECT_TRUE(FPDF_SaveAsCopy(saved_document_, this, 0));
Dan Sinclair04e4dc82017-10-18 12:17:14 -04002013
Lei Zhang107fa7b2018-02-09 21:48:15 +00002014 CloseSavedPage(saved_page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04002015 CloseSavedDocument();
wileyryae858aa42017-05-31 14:49:05 -05002016
2017 // Render the saved result
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002018 VerifySavedDocument(612, 792, kLastChecksum);
wileyryae858aa42017-05-31 14:49:05 -05002019}
2020
Lei Zhang03e5e682019-09-16 19:45:55 +00002021// TODO(crbug.com/pdfium/11): Fix this test and enable.
2022#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2023#define MAYBE_AddStrokedPaths DISABLED_AddStrokedPaths
2024#else
2025#define MAYBE_AddStrokedPaths AddStrokedPaths
2026#endif
2027TEST_F(FPDFEditEmbedderTest, MAYBE_AddStrokedPaths) {
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002028 // Start with a blank page
Nicolas Penad03ca422017-03-06 13:54:33 -05002029 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002030
2031 // Add a large stroked rectangle (fill color should not affect it).
2032 FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(20, 20, 200, 400);
Lei Zhang3475b482019-05-13 18:30:57 +00002033 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect, 255, 0, 0, 255));
2034 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(rect, 0, 255, 0, 255));
2035 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(rect, 15.0f));
Miklos Vajna366df7f2018-05-22 14:27:29 +00002036
2037 float width = 0;
2038 EXPECT_TRUE(FPDFPageObj_GetStrokeWidth(rect, &width));
2039 EXPECT_EQ(15.0f, width);
2040
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002041 EXPECT_TRUE(FPDFPath_SetDrawMode(rect, 0, 1));
2042 FPDFPage_InsertObject(page, rect);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002043 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002044 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002045 CompareBitmap(page_bitmap.get(), 612, 792,
2046 "64bd31f862a89e0a9e505a5af6efd506");
2047 }
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002048
2049 // Add crossed-checkmark
2050 FPDF_PAGEOBJECT check = FPDFPageObj_CreateNewPath(300, 500);
2051 EXPECT_TRUE(FPDFPath_LineTo(check, 400, 400));
2052 EXPECT_TRUE(FPDFPath_LineTo(check, 600, 600));
2053 EXPECT_TRUE(FPDFPath_MoveTo(check, 400, 600));
2054 EXPECT_TRUE(FPDFPath_LineTo(check, 600, 400));
Lei Zhang3475b482019-05-13 18:30:57 +00002055 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(check, 128, 128, 128, 180));
2056 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(check, 8.35f));
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002057 EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1));
2058 FPDFPage_InsertObject(page, check);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002059 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002060 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002061 CompareBitmap(page_bitmap.get(), 612, 792,
2062 "4b6f3b9d25c4e194821217d5016c3724");
2063 }
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002064
2065 // Add stroked and filled oval-ish path.
2066 FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(250, 100);
2067 EXPECT_TRUE(FPDFPath_BezierTo(path, 180, 166, 180, 233, 250, 300));
2068 EXPECT_TRUE(FPDFPath_LineTo(path, 255, 305));
2069 EXPECT_TRUE(FPDFPath_BezierTo(path, 325, 233, 325, 166, 255, 105));
2070 EXPECT_TRUE(FPDFPath_Close(path));
Lei Zhang3475b482019-05-13 18:30:57 +00002071 EXPECT_TRUE(FPDFPageObj_SetFillColor(path, 200, 128, 128, 100));
2072 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(path, 128, 200, 128, 150));
2073 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(path, 10.5f));
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002074 EXPECT_TRUE(FPDFPath_SetDrawMode(path, FPDF_FILLMODE_ALTERNATE, 1));
2075 FPDFPage_InsertObject(page, path);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002076 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002077 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002078 CompareBitmap(page_bitmap.get(), 612, 792,
2079 "ff3e6a22326754944cc6e56609acd73b");
2080 }
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002081 FPDF_ClosePage(page);
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002082}
Nicolas Pena49058402017-02-14 18:26:20 -05002083
Nicolas Pena4c48b102018-06-13 18:23:46 +00002084// Tests adding text from standard font using FPDFPageObj_NewTextObj.
Lei Zhang03e5e682019-09-16 19:45:55 +00002085// TODO(crbug.com/pdfium/11): Fix this test and enable.
2086#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2087#define MAYBE_AddStandardFontText DISABLED_AddStandardFontText
2088#else
2089#define MAYBE_AddStandardFontText AddStandardFontText
2090#endif
2091TEST_F(FPDFEditEmbedderTest, MAYBE_AddStandardFontText) {
Nicolas Pena49058402017-02-14 18:26:20 -05002092 // Start with a blank page
Nicolas Penad03ca422017-03-06 13:54:33 -05002093 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
Nicolas Pena49058402017-02-14 18:26:20 -05002094
2095 // Add some text to the page
Nicolas Penab3161852017-05-02 14:12:50 -04002096 FPDF_PAGEOBJECT text_object1 =
2097 FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
2098 EXPECT_TRUE(text_object1);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002099 ScopedFPDFWideString text1 = GetFPDFWideString(kBottomText);
Nicolas Penab3161852017-05-02 14:12:50 -04002100 EXPECT_TRUE(FPDFText_SetText(text_object1, text1.get()));
2101 FPDFPageObj_Transform(text_object1, 1, 0, 0, 1, 20, 20);
2102 FPDFPage_InsertObject(page, text_object1);
Lei Zhange039bab2019-03-18 19:57:56 +00002103 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002104 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002105 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002106 CompareBitmap(page_bitmap.get(), 612, 792, kBottomTextChecksum);
Lei Zhange039bab2019-03-18 19:57:56 +00002107
2108 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Hui Yingst3b6136a2020-06-09 00:39:33 +00002109 VerifySavedDocument(612, 792, kBottomTextChecksum);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002110 }
Nicolas Pena49058402017-02-14 18:26:20 -05002111
2112 // Try another font
Nicolas Penab3161852017-05-02 14:12:50 -04002113 FPDF_PAGEOBJECT text_object2 =
Nicolas Penad03ca422017-03-06 13:54:33 -05002114 FPDFPageObj_NewTextObj(document(), "TimesNewRomanBold", 15.0f);
Nicolas Penab3161852017-05-02 14:12:50 -04002115 EXPECT_TRUE(text_object2);
Lei Zhangf0f67682019-04-08 17:03:21 +00002116 ScopedFPDFWideString text2 =
Nicolas Penab3161852017-05-02 14:12:50 -04002117 GetFPDFWideString(L"Hi, I'm Bold. Times New Roman Bold.");
2118 EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
2119 FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 100, 600);
2120 FPDFPage_InsertObject(page, text_object2);
Lei Zhange039bab2019-03-18 19:57:56 +00002121 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002122 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002123 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang0c03d632020-07-30 17:05:36 +00002124#if defined(OS_APPLE)
Lei Zhang0f6b4342020-02-25 20:00:39 +00002125 const char md5[] = "26a516d923b0a18fbea0a24e3aca5562";
Lei Zhange67bcc72019-04-30 18:55:58 +00002126#elif defined(OS_WIN)
Lei Zhange039bab2019-03-18 19:57:56 +00002127 const char md5[] = "3755dd35abd4c605755369401ee85b2d";
Nicolas Pena49058402017-02-14 18:26:20 -05002128#else
Lei Zhange039bab2019-03-18 19:57:56 +00002129 const char md5[] = "76fcc7d08aa15445efd2e2ceb7c6cc3b";
Nicolas Pena5bcd9a32017-03-22 11:04:35 -04002130#endif
Lei Zhange039bab2019-03-18 19:57:56 +00002131 CompareBitmap(page_bitmap.get(), 612, 792, md5);
2132
2133 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2134 VerifySavedDocument(612, 792, md5);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002135 }
Nicolas Pena49058402017-02-14 18:26:20 -05002136
2137 // And some randomly transformed text
Nicolas Penab3161852017-05-02 14:12:50 -04002138 FPDF_PAGEOBJECT text_object3 =
Nicolas Penad03ca422017-03-06 13:54:33 -05002139 FPDFPageObj_NewTextObj(document(), "Courier-Bold", 20.0f);
Nicolas Penab3161852017-05-02 14:12:50 -04002140 EXPECT_TRUE(text_object3);
Lei Zhangf0f67682019-04-08 17:03:21 +00002141 ScopedFPDFWideString text3 = GetFPDFWideString(L"Can you read me? <:)>");
Nicolas Penab3161852017-05-02 14:12:50 -04002142 EXPECT_TRUE(FPDFText_SetText(text_object3, text3.get()));
2143 FPDFPageObj_Transform(text_object3, 1, 1.5, 2, 0.5, 200, 200);
2144 FPDFPage_InsertObject(page, text_object3);
Lei Zhange039bab2019-03-18 19:57:56 +00002145 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002146 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002147 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang0c03d632020-07-30 17:05:36 +00002148#if defined(OS_APPLE)
Lei Zhang0f6b4342020-02-25 20:00:39 +00002149 const char md5[] = "532024c9ded47843313bb64a060118f3";
Lei Zhange67bcc72019-04-30 18:55:58 +00002150#elif defined(OS_WIN)
Lei Zhanga2b70732019-06-25 08:34:22 +00002151 const char md5[] = "5ded49fe157f89627903553771431e3d";
Nicolas Pena49058402017-02-14 18:26:20 -05002152#else
Lei Zhanga2b70732019-06-25 08:34:22 +00002153 const char md5[] = "344534539aa7c5cc78404cfff4bde7fb";
Nicolas Pena5bcd9a32017-03-22 11:04:35 -04002154#endif
Lei Zhange039bab2019-03-18 19:57:56 +00002155 CompareBitmap(page_bitmap.get(), 612, 792, md5);
2156
2157 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2158 VerifySavedDocument(612, 792, md5);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002159 }
Nicolas Pena49058402017-02-14 18:26:20 -05002160
Lei Zhang8da98232019-12-11 23:29:33 +00002161 FS_MATRIX matrix;
2162 EXPECT_FALSE(FPDFTextObj_GetMatrix(nullptr, &matrix));
2163 EXPECT_TRUE(FPDFTextObj_GetMatrix(text_object3, &matrix));
2164 EXPECT_FLOAT_EQ(1.0f, matrix.a);
2165 EXPECT_FLOAT_EQ(1.5f, matrix.b);
2166 EXPECT_FLOAT_EQ(2.0f, matrix.c);
2167 EXPECT_FLOAT_EQ(0.5f, matrix.d);
2168 EXPECT_FLOAT_EQ(200.0f, matrix.e);
2169 EXPECT_FLOAT_EQ(200.0f, matrix.f);
Miklos Vajnac765d2a2018-06-19 15:45:42 +00002170
Miklos Vajna8625d3b2018-06-26 15:12:48 +00002171 EXPECT_EQ(0, FPDFTextObj_GetFontSize(nullptr));
2172 EXPECT_EQ(20, FPDFTextObj_GetFontSize(text_object3));
2173
Nicolas Pena49058402017-02-14 18:26:20 -05002174 // TODO(npm): Why are there issues with text rotated by 90 degrees?
2175 // TODO(npm): FPDF_SaveAsCopy not giving the desired result after this.
2176 FPDF_ClosePage(page);
Nicolas Pena49058402017-02-14 18:26:20 -05002177}
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002178
Daniel Hosseinian8cb6a652019-12-18 00:50:41 +00002179TEST_F(FPDFEditEmbedderTest, GetTextRenderMode) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002180 ASSERT_TRUE(OpenDocument("text_render_mode.pdf"));
Miklos Vajna1448cc12018-07-03 13:52:33 +00002181 FPDF_PAGE page = LoadPage(0);
2182 ASSERT_TRUE(page);
2183 ASSERT_EQ(2, FPDFPage_CountObjects(page));
2184
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002185 EXPECT_EQ(FPDF_TEXTRENDERMODE_UNKNOWN,
Daniel Hosseinian8cb6a652019-12-18 00:50:41 +00002186 FPDFTextObj_GetTextRenderMode(nullptr));
Miklos Vajna1448cc12018-07-03 13:52:33 +00002187
2188 FPDF_PAGEOBJECT fill = FPDFPage_GetObject(page, 0);
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002189 EXPECT_EQ(FPDF_TEXTRENDERMODE_FILL, FPDFTextObj_GetTextRenderMode(fill));
Miklos Vajna1448cc12018-07-03 13:52:33 +00002190
2191 FPDF_PAGEOBJECT stroke = FPDFPage_GetObject(page, 1);
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002192 EXPECT_EQ(FPDF_TEXTRENDERMODE_STROKE, FPDFTextObj_GetTextRenderMode(stroke));
2193
2194 UnloadPage(page);
2195}
2196
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002197TEST_F(FPDFEditEmbedderTest, SetTextRenderMode) {
Hui Yingst609f7d62020-04-23 23:14:13 +00002198#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002199 const char kOriginalChecksum[] = "4960c720a6cdb7b2b16be809cce58aff";
2200 const char kStrokeChecksum[] = "4c099cf9abc1565806bd7cd1cca5ac1a";
Hui Yingst609f7d62020-04-23 23:14:13 +00002201#else
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002202#if defined(OS_WIN)
2203 const char kOriginalChecksum[] = "de6e86bad3e9fda753a8471a45cfbb58";
2204#elif defined(OS_APPLE)
2205 const char kOriginalChecksum[] = "2453a9a524ee3f5f525dd21345ec4d81";
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002206#else
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002207 const char kOriginalChecksum[] = "5a012d2920ac075c39ffa9437ea42faa";
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002208#endif
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002209 const char kStrokeChecksum[] = "412e52e621b46bd77baf2162e1fb1a1d";
2210#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002211
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002212 {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002213 ASSERT_TRUE(OpenDocument("text_render_mode.pdf"));
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002214 FPDF_PAGE page = LoadPage(0);
2215 ASSERT_TRUE(page);
2216 ASSERT_EQ(2, FPDFPage_CountObjects(page));
2217
2218 // Check the bitmap
2219 {
2220 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002221 CompareBitmap(page_bitmap.get(), 612, 446, kOriginalChecksum);
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002222 }
2223
2224 // Cannot set on a null object.
2225 EXPECT_FALSE(
2226 FPDFTextObj_SetTextRenderMode(nullptr, FPDF_TEXTRENDERMODE_UNKNOWN));
2227 EXPECT_FALSE(
2228 FPDFTextObj_SetTextRenderMode(nullptr, FPDF_TEXTRENDERMODE_INVISIBLE));
2229
2230 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
2231 ASSERT_TRUE(page_object);
2232 EXPECT_EQ(FPDF_TEXTRENDERMODE_FILL,
2233 FPDFTextObj_GetTextRenderMode(page_object));
2234
2235 // Cannot set UNKNOWN as a render mode.
2236 EXPECT_FALSE(FPDFTextObj_SetTextRenderMode(page_object,
2237 FPDF_TEXTRENDERMODE_UNKNOWN));
2238
2239 EXPECT_TRUE(
2240 FPDFTextObj_SetTextRenderMode(page_object, FPDF_TEXTRENDERMODE_STROKE));
2241 EXPECT_EQ(FPDF_TEXTRENDERMODE_STROKE,
2242 FPDFTextObj_GetTextRenderMode(page_object));
2243
2244 // Check that bitmap displays changed content
2245 {
2246 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002247 CompareBitmap(page_bitmap.get(), 612, 446, kStrokeChecksum);
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002248 }
2249
Daniel Hosseinianafd27502020-07-01 04:59:03 +00002250 // Save a copy.
2251 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2252 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2253
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002254 UnloadPage(page);
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002255 }
Miklos Vajna1448cc12018-07-03 13:52:33 +00002256
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002257 {
Daniel Hosseinianafd27502020-07-01 04:59:03 +00002258 // Open the saved copy and render it. Check that the changed text render
2259 // mode is kept in the saved copy.
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002260 ASSERT_TRUE(OpenSavedDocument());
2261 FPDF_PAGE saved_page = LoadSavedPage(0);
2262 ASSERT_TRUE(saved_page);
2263
2264 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(saved_page, 0);
2265 EXPECT_TRUE(page_object);
Daniel Hosseinianafd27502020-07-01 04:59:03 +00002266 EXPECT_EQ(FPDF_TEXTRENDERMODE_STROKE,
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002267 FPDFTextObj_GetTextRenderMode(page_object));
2268
2269 ScopedFPDFBitmap bitmap = RenderSavedPage(saved_page);
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002270 CompareBitmap(bitmap.get(), 612, 446, kStrokeChecksum);
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002271
2272 CloseSavedPage(saved_page);
2273 CloseSavedDocument();
2274 }
Miklos Vajna1448cc12018-07-03 13:52:33 +00002275}
2276
Lei Zhangab41f252018-12-23 03:10:50 +00002277TEST_F(FPDFEditEmbedderTest, TestGetTextFontName) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002278 ASSERT_TRUE(OpenDocument("text_font.pdf"));
Miklos Vajna53d4f0a2018-08-01 01:28:49 +00002279 FPDF_PAGE page = LoadPage(0);
2280 ASSERT_TRUE(page);
2281 ASSERT_EQ(1, FPDFPage_CountObjects(page));
2282
2283 // FPDFTextObj_GetFontName() positive testing.
2284 FPDF_PAGEOBJECT text = FPDFPage_GetObject(page, 0);
2285 unsigned long size = FPDFTextObj_GetFontName(text, nullptr, 0);
2286 const char kExpectedFontName[] = "Liberation Serif";
2287 ASSERT_EQ(sizeof(kExpectedFontName), size);
2288 std::vector<char> font_name(size);
2289 ASSERT_EQ(size, FPDFTextObj_GetFontName(text, font_name.data(), size));
2290 ASSERT_STREQ(kExpectedFontName, font_name.data());
2291
2292 // FPDFTextObj_GetFontName() negative testing.
2293 ASSERT_EQ(0U, FPDFTextObj_GetFontName(nullptr, nullptr, 0));
2294
2295 font_name.resize(2);
2296 font_name[0] = 'x';
2297 font_name[1] = '\0';
2298 size = FPDFTextObj_GetFontName(text, font_name.data(), font_name.size());
2299 ASSERT_EQ(sizeof(kExpectedFontName), size);
2300 ASSERT_EQ(std::string("x"), std::string(font_name.data()));
2301
2302 UnloadPage(page);
2303}
2304
Lei Zhangab41f252018-12-23 03:10:50 +00002305TEST_F(FPDFEditEmbedderTest, TestFormGetObjects) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002306 ASSERT_TRUE(OpenDocument("form_object.pdf"));
Miklos Vajnab66077d2018-07-11 13:25:02 +00002307 FPDF_PAGE page = LoadPage(0);
2308 ASSERT_TRUE(page);
2309 ASSERT_EQ(1, FPDFPage_CountObjects(page));
2310
2311 FPDF_PAGEOBJECT form = FPDFPage_GetObject(page, 0);
2312 EXPECT_EQ(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(form));
2313 ASSERT_EQ(-1, FPDFFormObj_CountObjects(nullptr));
2314 ASSERT_EQ(2, FPDFFormObj_CountObjects(form));
2315
Miklos Vajna1d273f12018-07-16 19:20:36 +00002316 // FPDFFormObj_GetObject() positive testing.
2317 FPDF_PAGEOBJECT text1 = FPDFFormObj_GetObject(form, 0);
2318 ASSERT_TRUE(text1);
2319 float left = 0;
2320 float bottom = 0;
2321 float right = 0;
2322 float top = 0;
2323 ASSERT_TRUE(FPDFPageObj_GetBounds(text1, &left, &bottom, &right, &top));
2324 ASSERT_EQ(271, static_cast<int>(top));
2325
2326 FPDF_PAGEOBJECT text2 = FPDFFormObj_GetObject(form, 1);
2327 ASSERT_TRUE(text2);
2328 ASSERT_TRUE(FPDFPageObj_GetBounds(text2, &left, &bottom, &right, &top));
2329 ASSERT_EQ(221, static_cast<int>(top));
2330
2331 // FPDFFormObj_GetObject() negative testing.
2332 ASSERT_EQ(nullptr, FPDFFormObj_GetObject(nullptr, 0));
2333 ASSERT_EQ(nullptr, FPDFFormObj_GetObject(form, -1));
2334 ASSERT_EQ(nullptr, FPDFFormObj_GetObject(form, 2));
2335
Miklos Vajna46b43732018-08-14 19:15:43 +00002336 // Reset the form object matrix to identity.
2337 auto* pPageObj = CPDFPageObjectFromFPDFPageObject(form);
2338 CPDF_FormObject* pFormObj = pPageObj->AsForm();
2339 pFormObj->Transform(pFormObj->form_matrix().GetInverse());
2340
2341 // FPDFFormObj_GetMatrix() positive testing.
Lei Zhang8da98232019-12-11 23:29:33 +00002342 static constexpr FS_MATRIX kMatrix = {1.0f, 1.5f, 2.0f, 2.5f, 100.0f, 200.0f};
2343 pFormObj->Transform(CFXMatrixFromFSMatrix(kMatrix));
Miklos Vajna46b43732018-08-14 19:15:43 +00002344
Lei Zhang8da98232019-12-11 23:29:33 +00002345 FS_MATRIX matrix;
2346 EXPECT_TRUE(FPDFFormObj_GetMatrix(form, &matrix));
2347 EXPECT_FLOAT_EQ(kMatrix.a, matrix.a);
2348 EXPECT_FLOAT_EQ(kMatrix.b, matrix.b);
2349 EXPECT_FLOAT_EQ(kMatrix.c, matrix.c);
2350 EXPECT_FLOAT_EQ(kMatrix.d, matrix.d);
2351 EXPECT_FLOAT_EQ(kMatrix.e, matrix.e);
2352 EXPECT_FLOAT_EQ(kMatrix.f, matrix.f);
Miklos Vajna46b43732018-08-14 19:15:43 +00002353
2354 // FPDFFormObj_GetMatrix() negative testing.
Lei Zhang8da98232019-12-11 23:29:33 +00002355 EXPECT_FALSE(FPDFFormObj_GetMatrix(nullptr, &matrix));
2356 EXPECT_FALSE(FPDFFormObj_GetMatrix(form, nullptr));
2357 EXPECT_FALSE(FPDFFormObj_GetMatrix(nullptr, nullptr));
Miklos Vajna46b43732018-08-14 19:15:43 +00002358
Miklos Vajnab66077d2018-07-11 13:25:02 +00002359 UnloadPage(page);
2360}
2361
Nicolas Pena4c48b102018-06-13 18:23:46 +00002362// Tests adding text from standard font using FPDFText_LoadStandardFont.
Lei Zhang03e5e682019-09-16 19:45:55 +00002363// TODO(crbug.com/pdfium/11): Fix this test and enable.
2364#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2365#define MAYBE_AddStandardFontText2 DISABLED_AddStandardFontText2
2366#else
2367#define MAYBE_AddStandardFontText2 AddStandardFontText2
2368#endif
2369TEST_F(FPDFEditEmbedderTest, MAYBE_AddStandardFontText2) {
Nicolas Pena4c48b102018-06-13 18:23:46 +00002370 // Start with a blank page
2371 ScopedFPDFPage page(FPDFPage_New(CreateNewDocument(), 0, 612, 792));
2372
2373 // Load a standard font.
Tom Sepezffff6c52019-07-30 21:56:19 +00002374 ScopedFPDFFont font(FPDFText_LoadStandardFont(document(), "Helvetica"));
Nicolas Pena4c48b102018-06-13 18:23:46 +00002375 ASSERT_TRUE(font);
2376
2377 // Add some text to the page.
2378 FPDF_PAGEOBJECT text_object =
Tom Sepezffff6c52019-07-30 21:56:19 +00002379 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
Nicolas Pena4c48b102018-06-13 18:23:46 +00002380 EXPECT_TRUE(text_object);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002381 ScopedFPDFWideString text = GetFPDFWideString(kBottomText);
Nicolas Pena4c48b102018-06-13 18:23:46 +00002382 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2383 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 20, 20);
2384 FPDFPage_InsertObject(page.get(), text_object);
Lei Zhang30ff2532019-01-31 21:37:55 +00002385 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
Hui Yingst3b6136a2020-06-09 00:39:33 +00002386 CompareBitmap(page_bitmap.get(), 612, 792, kBottomTextChecksum);
Nicolas Pena4c48b102018-06-13 18:23:46 +00002387}
2388
Lei Zhangab41f252018-12-23 03:10:50 +00002389TEST_F(FPDFEditEmbedderTest, LoadStandardFonts) {
Nicolas Pena4c48b102018-06-13 18:23:46 +00002390 CreateNewDocument();
Lei Zhang590f4242019-05-15 20:57:26 +00002391 static constexpr const char* kStandardFontNames[] = {
Lei Zhangd72fd582018-07-27 19:37:27 +00002392 "Arial",
2393 "Arial-Bold",
2394 "Arial-BoldItalic",
2395 "Arial-Italic",
2396 "Courier",
2397 "Courier-BoldOblique",
2398 "Courier-Oblique",
2399 "Courier-Bold",
2400 "CourierNew",
2401 "CourierNew-Bold",
2402 "CourierNew-BoldItalic",
2403 "CourierNew-Italic",
2404 "Helvetica",
2405 "Helvetica-Bold",
2406 "Helvetica-BoldOblique",
2407 "Helvetica-Oblique",
2408 "Symbol",
2409 "TimesNewRoman",
2410 "TimesNewRoman-Bold",
2411 "TimesNewRoman-BoldItalic",
2412 "TimesNewRoman-Italic",
2413 "ZapfDingbats"};
Lei Zhang590f4242019-05-15 20:57:26 +00002414 for (const char* font_name : kStandardFontNames) {
Tom Sepezffff6c52019-07-30 21:56:19 +00002415 ScopedFPDFFont font(FPDFText_LoadStandardFont(document(), font_name));
Nicolas Pena4c48b102018-06-13 18:23:46 +00002416 EXPECT_TRUE(font) << font_name << " should be considered a standard font.";
2417 }
Lei Zhang590f4242019-05-15 20:57:26 +00002418 static constexpr const char* kNotStandardFontNames[] = {
Nicolas Pena4c48b102018-06-13 18:23:46 +00002419 "Abcdefg", "ArialB", "Arial-Style",
2420 "Font Name", "FontArial", "NotAStandardFontName",
2421 "TestFontName", "Quack", "Symbol-Italic",
2422 "Zapf"};
Lei Zhang590f4242019-05-15 20:57:26 +00002423 for (const char* font_name : kNotStandardFontNames) {
Tom Sepezffff6c52019-07-30 21:56:19 +00002424 ScopedFPDFFont font(FPDFText_LoadStandardFont(document(), font_name));
Nicolas Pena4c48b102018-06-13 18:23:46 +00002425 EXPECT_FALSE(font) << font_name
2426 << " should not be considered a standard font.";
2427 }
2428}
2429
Lei Zhangab41f252018-12-23 03:10:50 +00002430TEST_F(FPDFEditEmbedderTest, GraphicsData) {
Nicolas Pena603a31d2017-06-14 11:41:18 -04002431 // New page
Tom Sepeze08d2b12018-04-25 18:49:32 +00002432 ScopedFPDFPage page(FPDFPage_New(CreateNewDocument(), 0, 612, 792));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002433
2434 // Create a rect with nontrivial graphics
2435 FPDF_PAGEOBJECT rect1 = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
2436 FPDFPageObj_SetBlendMode(rect1, "Color");
2437 FPDFPage_InsertObject(page.get(), rect1);
2438 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
2439
2440 // Check that the ExtGState was created
Lei Zhang107fa7b2018-02-09 21:48:15 +00002441 CPDF_Page* cpage = CPDFPageFromFPDFPage(page.get());
2442 CPDF_Dictionary* graphics_dict = cpage->m_pResources->GetDictFor("ExtGState");
Nicolas Pena603a31d2017-06-14 11:41:18 -04002443 ASSERT_TRUE(graphics_dict);
Lei Zhangf40380f2018-10-12 18:31:51 +00002444 EXPECT_EQ(2u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002445
2446 // Add a text object causing no change to the graphics dictionary
2447 FPDF_PAGEOBJECT text1 = FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
2448 // Only alpha, the last component, matters for the graphics dictionary. And
2449 // the default value is 255.
Lei Zhang3475b482019-05-13 18:30:57 +00002450 EXPECT_TRUE(FPDFPageObj_SetFillColor(text1, 100, 100, 100, 255));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002451 FPDFPage_InsertObject(page.get(), text1);
2452 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002453 EXPECT_EQ(2u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002454
2455 // Add a text object increasing the size of the graphics dictionary
2456 FPDF_PAGEOBJECT text2 =
2457 FPDFPageObj_NewTextObj(document(), "Times-Roman", 12.0f);
2458 FPDFPage_InsertObject(page.get(), text2);
2459 FPDFPageObj_SetBlendMode(text2, "Darken");
Lei Zhang3475b482019-05-13 18:30:57 +00002460 EXPECT_TRUE(FPDFPageObj_SetFillColor(text2, 0, 0, 255, 150));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002461 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002462 EXPECT_EQ(3u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002463
2464 // Add a path that should reuse graphics
Nicolas Penace67be42017-06-14 14:52:49 -04002465 FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(400, 100);
Nicolas Pena603a31d2017-06-14 11:41:18 -04002466 FPDFPageObj_SetBlendMode(path, "Darken");
Lei Zhang3475b482019-05-13 18:30:57 +00002467 EXPECT_TRUE(FPDFPageObj_SetFillColor(path, 200, 200, 100, 150));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002468 FPDFPage_InsertObject(page.get(), path);
2469 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002470 EXPECT_EQ(3u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002471
2472 // Add a rect increasing the size of the graphics dictionary
2473 FPDF_PAGEOBJECT rect2 = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
2474 FPDFPageObj_SetBlendMode(rect2, "Darken");
Lei Zhang3475b482019-05-13 18:30:57 +00002475 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect2, 0, 0, 255, 150));
2476 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(rect2, 0, 0, 0, 200));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002477 FPDFPage_InsertObject(page.get(), rect2);
2478 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002479 EXPECT_EQ(4u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002480}
2481
Lei Zhangab41f252018-12-23 03:10:50 +00002482TEST_F(FPDFEditEmbedderTest, DoubleGenerating) {
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002483 // Start with a blank page
Nicolas Penad03ca422017-03-06 13:54:33 -05002484 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002485
2486 // Add a red rectangle with some non-default alpha
2487 FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
Lei Zhang3475b482019-05-13 18:30:57 +00002488 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect, 255, 0, 0, 128));
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002489 EXPECT_TRUE(FPDFPath_SetDrawMode(rect, FPDF_FILLMODE_WINDING, 0));
2490 FPDFPage_InsertObject(page, rect);
2491 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2492
2493 // Check the ExtGState
Lei Zhang107fa7b2018-02-09 21:48:15 +00002494 CPDF_Page* cpage = CPDFPageFromFPDFPage(page);
2495 CPDF_Dictionary* graphics_dict = cpage->m_pResources->GetDictFor("ExtGState");
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002496 ASSERT_TRUE(graphics_dict);
Lei Zhangf40380f2018-10-12 18:31:51 +00002497 EXPECT_EQ(2u, graphics_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002498
2499 // Check the bitmap
Lei Zhang107fa7b2018-02-09 21:48:15 +00002500 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002501 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002502 CompareBitmap(page_bitmap.get(), 612, 792,
2503 "5384da3406d62360ffb5cac4476fff1c");
2504 }
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002505
2506 // Never mind, my new favorite color is blue, increase alpha
Lei Zhang3475b482019-05-13 18:30:57 +00002507 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect, 0, 0, 255, 180));
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002508 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhangf40380f2018-10-12 18:31:51 +00002509 EXPECT_EQ(3u, graphics_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002510
2511 // Check that bitmap displays changed content
Lei Zhang107fa7b2018-02-09 21:48:15 +00002512 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002513 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002514 CompareBitmap(page_bitmap.get(), 612, 792,
2515 "2e51656f5073b0bee611d9cd086aa09c");
2516 }
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002517
2518 // And now generate, without changes
2519 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhangf40380f2018-10-12 18:31:51 +00002520 EXPECT_EQ(3u, graphics_dict->size());
Lei Zhang107fa7b2018-02-09 21:48:15 +00002521 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002522 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002523 CompareBitmap(page_bitmap.get(), 612, 792,
2524 "2e51656f5073b0bee611d9cd086aa09c");
2525 }
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002526
2527 // Add some text to the page
Nicolas Penab3161852017-05-02 14:12:50 -04002528 FPDF_PAGEOBJECT text_object =
2529 FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
Lei Zhangf0f67682019-04-08 17:03:21 +00002530 ScopedFPDFWideString text =
Nicolas Penab3161852017-05-02 14:12:50 -04002531 GetFPDFWideString(L"Something something #text# something");
2532 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2533 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 300, 300);
2534 FPDFPage_InsertObject(page, text_object);
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002535 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002536 CPDF_Dictionary* font_dict = cpage->m_pResources->GetDictFor("Font");
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002537 ASSERT_TRUE(font_dict);
Lei Zhangf40380f2018-10-12 18:31:51 +00002538 EXPECT_EQ(1u, font_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002539
2540 // Generate yet again, check dicts are reasonably sized
2541 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhangf40380f2018-10-12 18:31:51 +00002542 EXPECT_EQ(3u, graphics_dict->size());
2543 EXPECT_EQ(1u, font_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002544 FPDF_ClosePage(page);
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002545}
Nicolas Penabe90aae2017-02-27 10:41:41 -05002546
Lei Zhangab41f252018-12-23 03:10:50 +00002547TEST_F(FPDFEditEmbedderTest, LoadSimpleType1Font) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002548 CreateNewDocument();
2549 // TODO(npm): use other fonts after disallowing loading any font as any type
Tom Sepezffff6c52019-07-30 21:56:19 +00002550 RetainPtr<CPDF_Font> stock_font =
Nicolas Penad03ca422017-03-06 13:54:33 -05002551 CPDF_Font::GetStockFont(cpdf_doc(), "Times-Bold");
Tom Sepez20c41a52018-08-29 23:53:53 +00002552 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2553 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2554 FPDF_FONT_TYPE1, false));
Nicolas Penab3161852017-05-02 14:12:50 -04002555 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002556 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002557 EXPECT_TRUE(typed_font->IsType1Font());
Nicolas Penabe90aae2017-02-27 10:41:41 -05002558
Lei Zhang710fa992018-05-25 16:24:48 +00002559 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002560 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2561 EXPECT_EQ("Type1", font_dict->GetNameFor("Subtype"));
2562 EXPECT_EQ("TimesNewRomanPS-BoldMT", font_dict->GetNameFor("BaseFont"));
Nicolas Penabe90aae2017-02-27 10:41:41 -05002563 ASSERT_TRUE(font_dict->KeyExist("FirstChar"));
2564 ASSERT_TRUE(font_dict->KeyExist("LastChar"));
2565 EXPECT_EQ(32, font_dict->GetIntegerFor("FirstChar"));
Nicolas Penad03ca422017-03-06 13:54:33 -05002566 EXPECT_EQ(255, font_dict->GetIntegerFor("LastChar"));
2567
Lei Zhangde579ab2018-05-25 21:49:49 +00002568 const CPDF_Array* widths_array = font_dict->GetArrayFor("Widths");
Nicolas Penad03ca422017-03-06 13:54:33 -05002569 ASSERT_TRUE(widths_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002570 ASSERT_EQ(224u, widths_array->size());
Nicolas Penabe90aae2017-02-27 10:41:41 -05002571 EXPECT_EQ(250, widths_array->GetNumberAt(0));
Nicolas Penad03ca422017-03-06 13:54:33 -05002572 EXPECT_EQ(569, widths_array->GetNumberAt(11));
2573 EXPECT_EQ(500, widths_array->GetNumberAt(223));
Tom Sepez20c41a52018-08-29 23:53:53 +00002574 CheckFontDescriptor(font_dict, FPDF_FONT_TYPE1, true, false, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05002575}
Nicolas Penabe90aae2017-02-27 10:41:41 -05002576
Lei Zhangab41f252018-12-23 03:10:50 +00002577TEST_F(FPDFEditEmbedderTest, LoadSimpleTrueTypeFont) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002578 CreateNewDocument();
Tom Sepezffff6c52019-07-30 21:56:19 +00002579 RetainPtr<CPDF_Font> stock_font =
2580 CPDF_Font::GetStockFont(cpdf_doc(), "Courier");
Tom Sepez20c41a52018-08-29 23:53:53 +00002581 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2582 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2583 FPDF_FONT_TRUETYPE, false));
Nicolas Penab3161852017-05-02 14:12:50 -04002584 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002585 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002586 EXPECT_TRUE(typed_font->IsTrueTypeFont());
Nicolas Penabe90aae2017-02-27 10:41:41 -05002587
Lei Zhang710fa992018-05-25 16:24:48 +00002588 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002589 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2590 EXPECT_EQ("TrueType", font_dict->GetNameFor("Subtype"));
2591 EXPECT_EQ("CourierNewPSMT", font_dict->GetNameFor("BaseFont"));
Nicolas Penad03ca422017-03-06 13:54:33 -05002592 ASSERT_TRUE(font_dict->KeyExist("FirstChar"));
2593 ASSERT_TRUE(font_dict->KeyExist("LastChar"));
2594 EXPECT_EQ(32, font_dict->GetIntegerFor("FirstChar"));
2595 EXPECT_EQ(255, font_dict->GetIntegerFor("LastChar"));
Nicolas Penabe90aae2017-02-27 10:41:41 -05002596
Lei Zhangde579ab2018-05-25 21:49:49 +00002597 const CPDF_Array* widths_array = font_dict->GetArrayFor("Widths");
Nicolas Penad03ca422017-03-06 13:54:33 -05002598 ASSERT_TRUE(widths_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002599 ASSERT_EQ(224u, widths_array->size());
Nicolas Penad03ca422017-03-06 13:54:33 -05002600 EXPECT_EQ(600, widths_array->GetNumberAt(33));
2601 EXPECT_EQ(600, widths_array->GetNumberAt(74));
2602 EXPECT_EQ(600, widths_array->GetNumberAt(223));
Tom Sepez20c41a52018-08-29 23:53:53 +00002603 CheckFontDescriptor(font_dict, FPDF_FONT_TRUETYPE, false, false, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05002604}
2605
Lei Zhangab41f252018-12-23 03:10:50 +00002606TEST_F(FPDFEditEmbedderTest, LoadCIDType0Font) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002607 CreateNewDocument();
Tom Sepezffff6c52019-07-30 21:56:19 +00002608 RetainPtr<CPDF_Font> stock_font =
Nicolas Penad03ca422017-03-06 13:54:33 -05002609 CPDF_Font::GetStockFont(cpdf_doc(), "Times-Roman");
Tom Sepez20c41a52018-08-29 23:53:53 +00002610 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2611 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2612 FPDF_FONT_TYPE1, 1));
Nicolas Penab3161852017-05-02 14:12:50 -04002613 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002614 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002615 EXPECT_TRUE(typed_font->IsCIDFont());
2616
2617 // Check font dictionary entries
Lei Zhang710fa992018-05-25 16:24:48 +00002618 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002619 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2620 EXPECT_EQ("Type0", font_dict->GetNameFor("Subtype"));
2621 EXPECT_EQ("TimesNewRomanPSMT-Identity-H", font_dict->GetNameFor("BaseFont"));
2622 EXPECT_EQ("Identity-H", font_dict->GetNameFor("Encoding"));
Lei Zhangde579ab2018-05-25 21:49:49 +00002623 const CPDF_Array* descendant_array =
2624 font_dict->GetArrayFor("DescendantFonts");
Nicolas Penad03ca422017-03-06 13:54:33 -05002625 ASSERT_TRUE(descendant_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002626 EXPECT_EQ(1u, descendant_array->size());
Nicolas Penad03ca422017-03-06 13:54:33 -05002627
2628 // Check the CIDFontDict
Lei Zhangde579ab2018-05-25 21:49:49 +00002629 const CPDF_Dictionary* cidfont_dict = descendant_array->GetDictAt(0);
Lei Zhanga228ff32020-06-24 17:39:33 +00002630 EXPECT_EQ("Font", cidfont_dict->GetNameFor("Type"));
2631 EXPECT_EQ("CIDFontType0", cidfont_dict->GetNameFor("Subtype"));
2632 EXPECT_EQ("TimesNewRomanPSMT", cidfont_dict->GetNameFor("BaseFont"));
Lei Zhangb1ec2802018-05-25 21:55:24 +00002633 const CPDF_Dictionary* cidinfo_dict =
2634 cidfont_dict->GetDictFor("CIDSystemInfo");
Nicolas Penad03ca422017-03-06 13:54:33 -05002635 ASSERT_TRUE(cidinfo_dict);
Lei Zhang9c950b12019-01-16 19:06:37 +00002636 const CPDF_Object* registry = cidinfo_dict->GetObjectFor("Registry");
2637 ASSERT_TRUE(registry);
KDr28da0e1b2019-01-17 03:44:29 +00002638 EXPECT_EQ(CPDF_Object::kString, registry->GetType());
Lei Zhang9c950b12019-01-16 19:06:37 +00002639 EXPECT_EQ("Adobe", registry->GetString());
2640 const CPDF_Object* ordering = cidinfo_dict->GetObjectFor("Ordering");
2641 ASSERT_TRUE(ordering);
KDr28da0e1b2019-01-17 03:44:29 +00002642 EXPECT_EQ(CPDF_Object::kString, ordering->GetType());
Lei Zhang9c950b12019-01-16 19:06:37 +00002643 EXPECT_EQ("Identity", ordering->GetString());
Nicolas Penad03ca422017-03-06 13:54:33 -05002644 EXPECT_EQ(0, cidinfo_dict->GetNumberFor("Supplement"));
Tom Sepez20c41a52018-08-29 23:53:53 +00002645 CheckFontDescriptor(cidfont_dict, FPDF_FONT_TYPE1, false, false, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05002646
2647 // Check widths
Lei Zhangde579ab2018-05-25 21:49:49 +00002648 const CPDF_Array* widths_array = cidfont_dict->GetArrayFor("W");
Nicolas Penad03ca422017-03-06 13:54:33 -05002649 ASSERT_TRUE(widths_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002650 EXPECT_GT(widths_array->size(), 1u);
Nicolas Penad03ca422017-03-06 13:54:33 -05002651 CheckCompositeFontWidths(widths_array, typed_font);
2652}
2653
Lei Zhangab41f252018-12-23 03:10:50 +00002654TEST_F(FPDFEditEmbedderTest, LoadCIDType2Font) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002655 CreateNewDocument();
Tom Sepezffff6c52019-07-30 21:56:19 +00002656 RetainPtr<CPDF_Font> stock_font =
Nicolas Penad03ca422017-03-06 13:54:33 -05002657 CPDF_Font::GetStockFont(cpdf_doc(), "Helvetica-Oblique");
Tom Sepez20c41a52018-08-29 23:53:53 +00002658 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2659 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2660 FPDF_FONT_TRUETYPE, 1));
Nicolas Penab3161852017-05-02 14:12:50 -04002661 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002662 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002663 EXPECT_TRUE(typed_font->IsCIDFont());
2664
2665 // Check font dictionary entries
Lei Zhang710fa992018-05-25 16:24:48 +00002666 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002667 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2668 EXPECT_EQ("Type0", font_dict->GetNameFor("Subtype"));
2669 EXPECT_EQ("Arial-ItalicMT", font_dict->GetNameFor("BaseFont"));
2670 EXPECT_EQ("Identity-H", font_dict->GetNameFor("Encoding"));
Lei Zhangde579ab2018-05-25 21:49:49 +00002671 const CPDF_Array* descendant_array =
2672 font_dict->GetArrayFor("DescendantFonts");
Nicolas Penad03ca422017-03-06 13:54:33 -05002673 ASSERT_TRUE(descendant_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002674 EXPECT_EQ(1u, descendant_array->size());
Nicolas Penad03ca422017-03-06 13:54:33 -05002675
2676 // Check the CIDFontDict
Lei Zhangde579ab2018-05-25 21:49:49 +00002677 const CPDF_Dictionary* cidfont_dict = descendant_array->GetDictAt(0);
Lei Zhanga228ff32020-06-24 17:39:33 +00002678 EXPECT_EQ("Font", cidfont_dict->GetNameFor("Type"));
2679 EXPECT_EQ("CIDFontType2", cidfont_dict->GetNameFor("Subtype"));
2680 EXPECT_EQ("Arial-ItalicMT", cidfont_dict->GetNameFor("BaseFont"));
Lei Zhangb1ec2802018-05-25 21:55:24 +00002681 const CPDF_Dictionary* cidinfo_dict =
2682 cidfont_dict->GetDictFor("CIDSystemInfo");
Nicolas Penad03ca422017-03-06 13:54:33 -05002683 ASSERT_TRUE(cidinfo_dict);
2684 EXPECT_EQ("Adobe", cidinfo_dict->GetStringFor("Registry"));
2685 EXPECT_EQ("Identity", cidinfo_dict->GetStringFor("Ordering"));
2686 EXPECT_EQ(0, cidinfo_dict->GetNumberFor("Supplement"));
Tom Sepez20c41a52018-08-29 23:53:53 +00002687 CheckFontDescriptor(cidfont_dict, FPDF_FONT_TRUETYPE, false, true, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05002688
2689 // Check widths
Lei Zhangde579ab2018-05-25 21:49:49 +00002690 const CPDF_Array* widths_array = cidfont_dict->GetArrayFor("W");
Nicolas Penad03ca422017-03-06 13:54:33 -05002691 ASSERT_TRUE(widths_array);
2692 CheckCompositeFontWidths(widths_array, typed_font);
Nicolas Penabe90aae2017-02-27 10:41:41 -05002693}
rbpotterce8e51e2017-04-28 12:42:47 -07002694
Lei Zhangab41f252018-12-23 03:10:50 +00002695TEST_F(FPDFEditEmbedderTest, NormalizeNegativeRotation) {
rbpotterce8e51e2017-04-28 12:42:47 -07002696 // Load document with a -90 degree rotation
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002697 ASSERT_TRUE(OpenDocument("bug_713197.pdf"));
rbpotterce8e51e2017-04-28 12:42:47 -07002698 FPDF_PAGE page = LoadPage(0);
2699 EXPECT_NE(nullptr, page);
2700
2701 EXPECT_EQ(3, FPDFPage_GetRotation(page));
2702 UnloadPage(page);
2703}
Nicolas Penab3161852017-05-02 14:12:50 -04002704
Lei Zhang03e5e682019-09-16 19:45:55 +00002705// TODO(crbug.com/pdfium/11): Fix this test and enable.
2706#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2707#define MAYBE_AddTrueTypeFontText DISABLED_AddTrueTypeFontText
2708#else
2709#define MAYBE_AddTrueTypeFontText AddTrueTypeFontText
2710#endif
2711TEST_F(FPDFEditEmbedderTest, MAYBE_AddTrueTypeFontText) {
Nicolas Penab3161852017-05-02 14:12:50 -04002712 // Start with a blank page
2713 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
2714 {
Tom Sepezffff6c52019-07-30 21:56:19 +00002715 RetainPtr<CPDF_Font> stock_font =
2716 CPDF_Font::GetStockFont(cpdf_doc(), "Arial");
Tom Sepez20c41a52018-08-29 23:53:53 +00002717 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2718 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2719 FPDF_FONT_TRUETYPE, 0));
Nicolas Penab3161852017-05-02 14:12:50 -04002720 ASSERT_TRUE(font.get());
2721
2722 // Add some text to the page
2723 FPDF_PAGEOBJECT text_object =
2724 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
2725 EXPECT_TRUE(text_object);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002726 ScopedFPDFWideString text = GetFPDFWideString(kLoadedFontText);
Nicolas Penab3161852017-05-02 14:12:50 -04002727 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2728 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 400, 400);
2729 FPDFPage_InsertObject(page, text_object);
Lei Zhang30ff2532019-01-31 21:37:55 +00002730 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002731 CompareBitmap(page_bitmap.get(), 612, 792, kLoadedFontTextChecksum);
Nicolas Penab3161852017-05-02 14:12:50 -04002732
2733 // Add some more text, same font
2734 FPDF_PAGEOBJECT text_object2 =
2735 FPDFPageObj_CreateTextObj(document(), font.get(), 15.0f);
Lei Zhangf0f67682019-04-08 17:03:21 +00002736 ScopedFPDFWideString text2 = GetFPDFWideString(L"Bigger font size");
Nicolas Penab3161852017-05-02 14:12:50 -04002737 EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
2738 FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 200, 200);
2739 FPDFPage_InsertObject(page, text_object2);
Nicolas Penab3161852017-05-02 14:12:50 -04002740 }
Lei Zhang30ff2532019-01-31 21:37:55 +00002741 ScopedFPDFBitmap page_bitmap2 = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002742#if defined(OS_WIN)
2743 const char kInsertTrueTypeChecksum[] = "2199b579c49ab5f80c246a586a80ee90";
Lei Zhang0c03d632020-07-30 17:05:36 +00002744#elif defined(OS_APPLE)
Hui Yingst3b6136a2020-06-09 00:39:33 +00002745 const char kInsertTrueTypeChecksum[] = "9a1a7dfebe659513691aadd0d95b8d50";
Nicolas Penab3161852017-05-02 14:12:50 -04002746#else
Hui Yingst3b6136a2020-06-09 00:39:33 +00002747 const char kInsertTrueTypeChecksum[] = "c1d10cce1761c4a998a16b2562030568";
Lei Zhange4cdac52019-04-30 16:45:57 +00002748#endif
Hui Yingst3b6136a2020-06-09 00:39:33 +00002749 CompareBitmap(page_bitmap2.get(), 612, 792, kInsertTrueTypeChecksum);
Nicolas Penab3161852017-05-02 14:12:50 -04002750
Nicolas Pena207b7272017-05-26 17:37:06 -04002751 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Nicolas Penab3161852017-05-02 14:12:50 -04002752 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2753 FPDF_ClosePage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04002754
Hui Yingst3b6136a2020-06-09 00:39:33 +00002755 VerifySavedDocument(612, 792, kInsertTrueTypeChecksum);
Nicolas Penab3161852017-05-02 14:12:50 -04002756}
Nicolas Penaf45ade32017-05-03 10:23:49 -04002757
Lei Zhangab41f252018-12-23 03:10:50 +00002758TEST_F(FPDFEditEmbedderTest, TransformAnnot) {
Jane Liueda65252017-06-07 11:31:27 -04002759 // Open a file with one annotation and load its first page.
2760 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00002761 FPDF_PAGE page = LoadPage(0);
Jane Liueda65252017-06-07 11:31:27 -04002762 ASSERT_TRUE(page);
2763
Lei Zhanga21d5932018-02-05 18:28:38 +00002764 {
2765 // Add an underline annotation to the page without specifying its rectangle.
Tom Sepeze08d2b12018-04-25 18:49:32 +00002766 ScopedFPDFAnnotation annot(
Lei Zhanga21d5932018-02-05 18:28:38 +00002767 FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE));
2768 ASSERT_TRUE(annot);
Jane Liueda65252017-06-07 11:31:27 -04002769
Lei Zhanga21d5932018-02-05 18:28:38 +00002770 // FPDFPage_TransformAnnots() should run without errors when modifying
2771 // annotation rectangles.
2772 FPDFPage_TransformAnnots(page, 1, 2, 3, 4, 5, 6);
2773 }
Jane Liueda65252017-06-07 11:31:27 -04002774 UnloadPage(page);
2775}
2776
Nicolas Penaf45ade32017-05-03 10:23:49 -04002777// TODO(npm): Add tests using Japanese fonts in other OS.
Lei Zhangfe8e7582020-08-05 19:23:16 +00002778#if defined(OS_LINUX) || defined(OS_CHROMEOS)
Lei Zhang03e5e682019-09-16 19:45:55 +00002779// TODO(crbug.com/pdfium/11): Fix this test and enable.
2780#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2781#define MAYBE_AddCIDFontText DISABLED_AddCIDFontText
2782#else
2783#define MAYBE_AddCIDFontText AddCIDFontText
2784#endif
2785TEST_F(FPDFEditEmbedderTest, MAYBE_AddCIDFontText) {
Nicolas Penaf45ade32017-05-03 10:23:49 -04002786 // Start with a blank page
2787 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
2788 CFX_Font CIDfont;
2789 {
2790 // First, get the data from the font
2791 CIDfont.LoadSubst("IPAGothic", 1, 0, 400, 0, 932, 0);
2792 EXPECT_EQ("IPAGothic", CIDfont.GetFaceName());
Tom Sepez20c41a52018-08-29 23:53:53 +00002793 pdfium::span<const uint8_t> span = CIDfont.GetFontSpan();
Nicolas Penaf45ade32017-05-03 10:23:49 -04002794
2795 // Load the data into a FPDF_Font.
Tom Sepez20c41a52018-08-29 23:53:53 +00002796 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2797 FPDF_FONT_TRUETYPE, 1));
Nicolas Penaf45ade32017-05-03 10:23:49 -04002798 ASSERT_TRUE(font.get());
2799
2800 // Add some text to the page
2801 FPDF_PAGEOBJECT text_object =
2802 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
2803 ASSERT_TRUE(text_object);
2804 std::wstring wstr = L"ABCDEFGhijklmnop.";
Lei Zhangf0f67682019-04-08 17:03:21 +00002805 ScopedFPDFWideString text = GetFPDFWideString(wstr);
Nicolas Penaf45ade32017-05-03 10:23:49 -04002806 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2807 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 200, 200);
2808 FPDFPage_InsertObject(page, text_object);
2809
2810 // And add some Japanese characters
2811 FPDF_PAGEOBJECT text_object2 =
2812 FPDFPageObj_CreateTextObj(document(), font.get(), 18.0f);
2813 ASSERT_TRUE(text_object2);
2814 std::wstring wstr2 =
2815 L"\u3053\u3093\u306B\u3061\u306f\u4e16\u754C\u3002\u3053\u3053\u306B1"
2816 L"\u756A";
Lei Zhangf0f67682019-04-08 17:03:21 +00002817 ScopedFPDFWideString text2 = GetFPDFWideString(wstr2);
Nicolas Penaf45ade32017-05-03 10:23:49 -04002818 EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
2819 FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 100, 500);
2820 FPDFPage_InsertObject(page, text_object2);
2821 }
2822
Nicolas Pena207b7272017-05-26 17:37:06 -04002823 // Check that the text renders properly.
Lei Zhanga2b70732019-06-25 08:34:22 +00002824 const char md5[] = "5159a72903fe57bf0cf645c894de8a74";
Lei Zhang107fa7b2018-02-09 21:48:15 +00002825 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002826 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002827 CompareBitmap(page_bitmap.get(), 612, 792, md5);
2828 }
Nicolas Penaf45ade32017-05-03 10:23:49 -04002829
2830 // Save the document, close the page.
Nicolas Pena207b7272017-05-26 17:37:06 -04002831 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Nicolas Penaf45ade32017-05-03 10:23:49 -04002832 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2833 FPDF_ClosePage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04002834
2835 VerifySavedDocument(612, 792, md5);
Nicolas Penaf45ade32017-05-03 10:23:49 -04002836}
Lei Zhangfe8e7582020-08-05 19:23:16 +00002837#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04002838
Lei Zhang03e5e682019-09-16 19:45:55 +00002839// TODO(crbug.com/pdfium/11): Fix this test and enable.
2840#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2841#define MAYBE_SaveAndRender DISABLED_SaveAndRender
2842#else
2843#define MAYBE_SaveAndRender SaveAndRender
2844#endif
2845TEST_F(FPDFEditEmbedderTest, MAYBE_SaveAndRender) {
Nicolas Penaa0b48aa2017-06-29 11:01:46 -04002846 const char md5[] = "3c20472b0552c0c22b88ab1ed8c6202b";
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04002847 {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002848 ASSERT_TRUE(OpenDocument("bug_779.pdf"));
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04002849 FPDF_PAGE page = LoadPage(0);
2850 ASSERT_NE(nullptr, page);
2851
2852 // Now add a more complex blue path.
2853 FPDF_PAGEOBJECT green_path = FPDFPageObj_CreateNewPath(20, 20);
Lei Zhang3475b482019-05-13 18:30:57 +00002854 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_path, 0, 255, 0, 200));
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04002855 // TODO(npm): stroking will cause the MD5s to differ.
2856 EXPECT_TRUE(FPDFPath_SetDrawMode(green_path, FPDF_FILLMODE_WINDING, 0));
2857 EXPECT_TRUE(FPDFPath_LineTo(green_path, 20, 63));
2858 EXPECT_TRUE(FPDFPath_BezierTo(green_path, 55, 55, 78, 78, 90, 90));
2859 EXPECT_TRUE(FPDFPath_LineTo(green_path, 133, 133));
2860 EXPECT_TRUE(FPDFPath_LineTo(green_path, 133, 33));
2861 EXPECT_TRUE(FPDFPath_BezierTo(green_path, 38, 33, 39, 36, 40, 40));
2862 EXPECT_TRUE(FPDFPath_Close(green_path));
2863 FPDFPage_InsertObject(page, green_path);
Tom Sepeze08d2b12018-04-25 18:49:32 +00002864 ScopedFPDFBitmap page_bitmap = RenderLoadedPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002865 CompareBitmap(page_bitmap.get(), 612, 792, md5);
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04002866
2867 // Now save the result, closing the page and document
2868 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2869 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2870 UnloadPage(page);
2871 }
Dan Sinclair04e4dc82017-10-18 12:17:14 -04002872
2873 VerifySavedDocument(612, 792, md5);
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04002874}
Jane Liu28fb7ba2017-08-02 21:45:57 -04002875
Lei Zhangab41f252018-12-23 03:10:50 +00002876TEST_F(FPDFEditEmbedderTest, AddMark) {
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00002877 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002878 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00002879 FPDF_PAGE page = LoadPage(0);
2880 ASSERT_TRUE(page);
2881
Lei Zhang2697cb12019-07-03 18:14:29 +00002882 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00002883
2884 // Add to the first page object a "Bounds" mark with "Position": "First".
2885 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
2886 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_AddMark(page_object, "Bounds");
2887 EXPECT_TRUE(mark);
Henrique Nakashimaa3406772018-07-13 19:10:53 +00002888 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), page_object, mark,
2889 "Position", "First"));
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00002890
Lei Zhang2697cb12019-07-03 18:14:29 +00002891 CheckMarkCounts(page, 1, 19, 8, 4, 9, 2);
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00002892
2893 // Save the file
2894 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2895 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2896 UnloadPage(page);
2897
2898 // Re-open the file and check the new mark is present.
Lei Zhang0b494052019-01-31 21:41:15 +00002899 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00002900 FPDF_PAGE saved_page = LoadSavedPage(0);
2901
Lei Zhang2697cb12019-07-03 18:14:29 +00002902 CheckMarkCounts(saved_page, 1, 19, 8, 4, 9, 2);
2903
2904 CloseSavedPage(saved_page);
2905 CloseSavedDocument();
2906}
2907
Hui Yingst04440af2020-07-27 22:39:02 +00002908TEST_F(FPDFEditEmbedderTest, AddMarkCompressedStream) {
Lei Zhang2697cb12019-07-03 18:14:29 +00002909 // Load document with some text in a compressed stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002910 ASSERT_TRUE(OpenDocument("hello_world_compressed_stream.pdf"));
Lei Zhang2697cb12019-07-03 18:14:29 +00002911 FPDF_PAGE page = LoadPage(0);
2912 ASSERT_TRUE(page);
2913
2914 // Render and check there are no marks.
2915 {
2916 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00002917 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Lei Zhang2697cb12019-07-03 18:14:29 +00002918 }
2919 CheckMarkCounts(page, 0, 2, 0, 0, 0, 0);
2920
2921 // Add to the first page object a "Bounds" mark with "Position": "First".
2922 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
2923 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_AddMark(page_object, "Bounds");
2924 EXPECT_TRUE(mark);
2925 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), page_object, mark,
2926 "Position", "First"));
2927
2928 // Render and check there is 1 mark.
2929 {
2930 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00002931 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Lei Zhang2697cb12019-07-03 18:14:29 +00002932 }
2933 CheckMarkCounts(page, 0, 2, 0, 0, 0, 1);
2934
2935 // Save the file.
2936 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2937 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2938 UnloadPage(page);
2939
2940 // Re-open the file and check the new mark is present.
2941 ASSERT_TRUE(OpenSavedDocument());
2942 FPDF_PAGE saved_page = LoadSavedPage(0);
2943
2944 {
2945 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00002946 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Lei Zhang2697cb12019-07-03 18:14:29 +00002947 }
2948 CheckMarkCounts(saved_page, 0, 2, 0, 0, 0, 1);
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00002949
2950 CloseSavedPage(saved_page);
2951 CloseSavedDocument();
2952}
2953
Lei Zhangab41f252018-12-23 03:10:50 +00002954TEST_F(FPDFEditEmbedderTest, SetMarkParam) {
Henrique Nakashimaa3406772018-07-13 19:10:53 +00002955 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002956 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimaa3406772018-07-13 19:10:53 +00002957 FPDF_PAGE page = LoadPage(0);
2958 ASSERT_TRUE(page);
2959
2960 constexpr int kExpectedObjectCount = 19;
2961 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
2962
2963 // Check the "Bounds" mark's "Position" param is "Last".
2964 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
2965 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
2966 ASSERT_TRUE(mark);
2967 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00002968 unsigned long name_len = 999u;
2969 ASSERT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
2970 EXPECT_EQ((6u + 1u) * 2u, name_len);
Henrique Nakashimaa3406772018-07-13 19:10:53 +00002971 ASSERT_EQ(L"Bounds",
2972 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
2973 unsigned long out_buffer_len;
2974 ASSERT_TRUE(FPDFPageObjMark_GetParamStringValue(
2975 mark, "Position", buffer, sizeof(buffer), &out_buffer_len));
2976 ASSERT_EQ(L"Last",
2977 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
2978
2979 // Set is to "End".
2980 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), page_object, mark,
2981 "Position", "End"));
2982
2983 // Verify the object passed must correspond to the mark passed.
2984 FPDF_PAGEOBJECT another_page_object = FPDFPage_GetObject(page, 17);
2985 EXPECT_FALSE(FPDFPageObjMark_SetStringParam(document(), another_page_object,
2986 mark, "Position", "End"));
2987
2988 // Verify nothing else changed.
2989 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
2990
2991 // Verify "Position" now maps to "End".
2992 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
2993 mark, "Position", buffer, sizeof(buffer), &out_buffer_len));
2994 EXPECT_EQ(L"End",
2995 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
2996
2997 // Save the file
2998 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2999 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3000 UnloadPage(page);
3001
3002 // Re-open the file and cerify "Position" still maps to "End".
Lei Zhang0b494052019-01-31 21:41:15 +00003003 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003004 FPDF_PAGE saved_page = LoadSavedPage(0);
3005
3006 CheckMarkCounts(saved_page, 1, kExpectedObjectCount, 8, 4, 9, 1);
3007 page_object = FPDFPage_GetObject(saved_page, 18);
3008 mark = FPDFPageObj_GetMark(page_object, 1);
3009 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
3010 mark, "Position", buffer, sizeof(buffer), &out_buffer_len));
3011 EXPECT_EQ(L"End",
3012 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3013
3014 CloseSavedPage(saved_page);
3015 CloseSavedDocument();
3016}
3017
Lei Zhang03e5e682019-09-16 19:45:55 +00003018// TODO(crbug.com/pdfium/11): Fix this test and enable.
3019#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
3020#define MAYBE_AddMarkedText DISABLED_AddMarkedText
3021#else
3022#define MAYBE_AddMarkedText AddMarkedText
3023#endif
3024TEST_F(FPDFEditEmbedderTest, MAYBE_AddMarkedText) {
Henrique Nakashima144107d2018-07-10 21:04:05 +00003025 // Start with a blank page.
3026 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
3027
Tom Sepezffff6c52019-07-30 21:56:19 +00003028 RetainPtr<CPDF_Font> stock_font =
3029 CPDF_Font::GetStockFont(cpdf_doc(), "Arial");
Tom Sepez20c41a52018-08-29 23:53:53 +00003030 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
3031 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
3032 FPDF_FONT_TRUETYPE, 0));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003033 ASSERT_TRUE(font.get());
3034
3035 // Add some text to the page.
3036 FPDF_PAGEOBJECT text_object =
3037 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
3038
3039 EXPECT_TRUE(text_object);
Hui Yingst3b6136a2020-06-09 00:39:33 +00003040 ScopedFPDFWideString text1 = GetFPDFWideString(kLoadedFontText);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003041 EXPECT_TRUE(FPDFText_SetText(text_object, text1.get()));
3042 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 400, 400);
3043 FPDFPage_InsertObject(page, text_object);
3044
3045 // Add a mark with the tag "TestMarkName" to that text.
3046 EXPECT_EQ(0, FPDFPageObj_CountMarks(text_object));
Henrique Nakashima6fc8d872018-09-18 16:48:31 +00003047 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_AddMark(text_object, "Test Mark Name");
Henrique Nakashima144107d2018-07-10 21:04:05 +00003048 EXPECT_TRUE(mark);
3049 EXPECT_EQ(1, FPDFPageObj_CountMarks(text_object));
3050 EXPECT_EQ(mark, FPDFPageObj_GetMark(text_object, 0));
3051 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003052 unsigned long name_len = 999u;
3053 ASSERT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
3054 EXPECT_EQ((14u + 1u) * 2, name_len);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003055 std::wstring name =
3056 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
Henrique Nakashima6fc8d872018-09-18 16:48:31 +00003057 EXPECT_EQ(L"Test Mark Name", name);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003058
3059 // Add parameters:
3060 // - int "IntKey" : 42
3061 // - string "StringKey": "StringValue"
Henrique Nakashima07520f62018-07-12 19:45:29 +00003062 // - blob "BlobKey": "\x01\x02\x03\0BlobValue1\0\0\0BlobValue2\0"
Lei Zhang590f4242019-05-15 20:57:26 +00003063 constexpr size_t kBlobLen = 28;
Lei Zhangd3b028b2018-11-30 22:22:00 +00003064 char block_value[kBlobLen];
3065 memcpy(block_value, "\x01\x02\x03\0BlobValue1\0\0\0BlobValue2\0", kBlobLen);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003066 EXPECT_EQ(0, FPDFPageObjMark_CountParams(mark));
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003067 EXPECT_TRUE(
3068 FPDFPageObjMark_SetIntParam(document(), text_object, mark, "IntKey", 42));
3069 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), text_object, mark,
3070 "StringKey", "StringValue"));
3071 EXPECT_TRUE(FPDFPageObjMark_SetBlobParam(document(), text_object, mark,
Lei Zhangd3b028b2018-11-30 22:22:00 +00003072 "BlobKey", block_value, kBlobLen));
Henrique Nakashima07520f62018-07-12 19:45:29 +00003073 EXPECT_EQ(3, FPDFPageObjMark_CountParams(mark));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003074
3075 // Check the two parameters can be retrieved.
3076 EXPECT_EQ(FPDF_OBJECT_NUMBER,
Henrique Nakashima94230e52018-07-11 22:02:02 +00003077 FPDFPageObjMark_GetParamValueType(mark, "IntKey"));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003078 int int_value;
Henrique Nakashima94230e52018-07-11 22:02:02 +00003079 EXPECT_TRUE(FPDFPageObjMark_GetParamIntValue(mark, "IntKey", &int_value));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003080 EXPECT_EQ(42, int_value);
3081
3082 EXPECT_EQ(FPDF_OBJECT_STRING,
Henrique Nakashima94230e52018-07-11 22:02:02 +00003083 FPDFPageObjMark_GetParamValueType(mark, "StringKey"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003084 unsigned long out_buffer_len = 999u;
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003085 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
3086 mark, "StringKey", buffer, sizeof(buffer), &out_buffer_len));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003087 EXPECT_GT(out_buffer_len, 0u);
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003088 EXPECT_NE(999u, out_buffer_len);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003089 name = GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
3090 EXPECT_EQ(L"StringValue", name);
3091
Henrique Nakashima07520f62018-07-12 19:45:29 +00003092 EXPECT_EQ(FPDF_OBJECT_STRING,
3093 FPDFPageObjMark_GetParamValueType(mark, "BlobKey"));
3094 out_buffer_len = 0;
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003095 EXPECT_TRUE(FPDFPageObjMark_GetParamBlobValue(
3096 mark, "BlobKey", buffer, sizeof(buffer), &out_buffer_len));
Henrique Nakashima07520f62018-07-12 19:45:29 +00003097 EXPECT_EQ(kBlobLen, out_buffer_len);
Lei Zhangd3b028b2018-11-30 22:22:00 +00003098 EXPECT_EQ(0, memcmp(block_value, buffer, kBlobLen));
Henrique Nakashima07520f62018-07-12 19:45:29 +00003099
Lei Zhangf16376e2020-06-18 19:19:32 +00003100 // Render and check the bitmap is the expected one.
Henrique Nakashima144107d2018-07-10 21:04:05 +00003101 {
Lei Zhang30ff2532019-01-31 21:37:55 +00003102 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00003103 CompareBitmap(page_bitmap.get(), 612, 792, kLoadedFontTextChecksum);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003104 }
3105
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003106 // Now save the result.
3107 EXPECT_EQ(1, FPDFPage_CountObjects(page));
3108 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3109 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3110
Henrique Nakashima144107d2018-07-10 21:04:05 +00003111 FPDF_ClosePage(page);
3112
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003113 // Re-open the file and check the changes were kept in the saved .pdf.
Lei Zhang0b494052019-01-31 21:41:15 +00003114 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003115 FPDF_PAGE saved_page = LoadSavedPage(0);
3116 EXPECT_EQ(1, FPDFPage_CountObjects(saved_page));
3117
3118 text_object = FPDFPage_GetObject(saved_page, 0);
3119 EXPECT_TRUE(text_object);
3120 EXPECT_EQ(1, FPDFPageObj_CountMarks(text_object));
3121 mark = FPDFPageObj_GetMark(text_object, 0);
3122 EXPECT_TRUE(mark);
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003123
3124 name_len = 999u;
3125 ASSERT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
3126 EXPECT_EQ((14u + 1u) * 2, name_len);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003127 name = GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
Henrique Nakashima6fc8d872018-09-18 16:48:31 +00003128 EXPECT_EQ(L"Test Mark Name", name);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003129
3130 CloseSavedPage(saved_page);
3131 CloseSavedDocument();
Henrique Nakashima144107d2018-07-10 21:04:05 +00003132}
3133
Lei Zhangab41f252018-12-23 03:10:50 +00003134TEST_F(FPDFEditEmbedderTest, MarkGetName) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003135 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003136 FPDF_PAGE page = LoadPage(0);
3137 ASSERT_TRUE(page);
3138 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
3139 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
3140 ASSERT_TRUE(mark);
3141
3142 char buffer[256];
3143 unsigned long out_len;
3144
3145 // Show the positive cases of FPDFPageObjMark_GetName.
3146 out_len = 999u;
3147 EXPECT_TRUE(FPDFPageObjMark_GetName(mark, nullptr, 0, &out_len));
3148 EXPECT_EQ((6u + 1u) * 2u, out_len);
3149
3150 out_len = 999u;
3151 EXPECT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &out_len));
3152 EXPECT_EQ(L"Bounds",
3153 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3154 EXPECT_EQ((6u + 1u) * 2u, out_len);
3155
3156 // Show the negative cases of FPDFPageObjMark_GetName.
3157 out_len = 999u;
3158 EXPECT_FALSE(
3159 FPDFPageObjMark_GetName(nullptr, buffer, sizeof(buffer), &out_len));
3160 EXPECT_EQ(999u, out_len);
3161
3162 EXPECT_FALSE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), nullptr));
3163
3164 UnloadPage(page);
3165}
3166
Lei Zhangab41f252018-12-23 03:10:50 +00003167TEST_F(FPDFEditEmbedderTest, MarkGetParamKey) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003168 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003169 FPDF_PAGE page = LoadPage(0);
3170 ASSERT_TRUE(page);
3171 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
3172 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
3173 ASSERT_TRUE(mark);
3174
3175 char buffer[256];
3176 unsigned long out_len;
3177
3178 // Show the positive cases of FPDFPageObjMark_GetParamKey.
3179 out_len = 999u;
3180 EXPECT_TRUE(FPDFPageObjMark_GetParamKey(mark, 0, nullptr, 0, &out_len));
3181 EXPECT_EQ((8u + 1u) * 2u, out_len);
3182
3183 out_len = 999u;
3184 EXPECT_TRUE(
3185 FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer), &out_len));
3186 EXPECT_EQ(L"Position",
3187 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3188 EXPECT_EQ((8u + 1u) * 2u, out_len);
3189
3190 // Show the negative cases of FPDFPageObjMark_GetParamKey.
3191 out_len = 999u;
3192 EXPECT_FALSE(FPDFPageObjMark_GetParamKey(nullptr, 0, buffer, sizeof(buffer),
3193 &out_len));
3194 EXPECT_EQ(999u, out_len);
3195
3196 out_len = 999u;
3197 EXPECT_FALSE(
3198 FPDFPageObjMark_GetParamKey(mark, 1, buffer, sizeof(buffer), &out_len));
3199 EXPECT_EQ(999u, out_len);
3200
3201 EXPECT_FALSE(
3202 FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer), nullptr));
3203
3204 UnloadPage(page);
3205}
3206
Lei Zhangab41f252018-12-23 03:10:50 +00003207TEST_F(FPDFEditEmbedderTest, MarkGetIntParam) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003208 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003209 FPDF_PAGE page = LoadPage(0);
3210 ASSERT_TRUE(page);
3211 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 8);
3212 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 0);
3213 ASSERT_TRUE(mark);
3214
3215 int out_value;
3216
3217 // Show the positive cases of FPDFPageObjMark_GetParamIntValue.
3218 out_value = 999;
3219 EXPECT_TRUE(FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
3220 EXPECT_EQ(3, out_value);
3221
3222 // Show the negative cases of FPDFPageObjMark_GetParamIntValue.
3223 out_value = 999;
3224 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(nullptr, "Factor", &out_value));
3225 EXPECT_EQ(999, out_value);
3226
3227 out_value = 999;
3228 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(mark, "ParamThatDoesNotExist",
3229 &out_value));
3230 EXPECT_EQ(999, out_value);
3231
3232 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(mark, "Factor", nullptr));
3233
3234 page_object = FPDFPage_GetObject(page, 18);
3235 mark = FPDFPageObj_GetMark(page_object, 1);
3236 out_value = 999;
3237 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(mark, "Position", &out_value));
3238 EXPECT_EQ(999, out_value);
3239
3240 UnloadPage(page);
3241}
3242
Lei Zhangab41f252018-12-23 03:10:50 +00003243TEST_F(FPDFEditEmbedderTest, MarkGetStringParam) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003244 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003245 FPDF_PAGE page = LoadPage(0);
3246 ASSERT_TRUE(page);
3247 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
3248 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
3249 ASSERT_TRUE(mark);
3250
3251 char buffer[256];
3252 unsigned long out_len;
3253
3254 // Show the positive cases of FPDFPageObjMark_GetParamStringValue.
3255 out_len = 999u;
3256 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(mark, "Position", nullptr, 0,
3257 &out_len));
3258 EXPECT_EQ((4u + 1u) * 2u, out_len);
3259
3260 out_len = 999u;
3261 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(mark, "Position", buffer,
3262 sizeof(buffer), &out_len));
3263 EXPECT_EQ(L"Last",
3264 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3265 EXPECT_EQ((4u + 1u) * 2u, out_len);
3266
3267 // Show the negative cases of FPDFPageObjMark_GetParamStringValue.
3268 out_len = 999u;
3269 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(nullptr, "Position", buffer,
3270 sizeof(buffer), &out_len));
3271 EXPECT_EQ(999u, out_len);
3272
3273 out_len = 999u;
3274 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(
3275 mark, "ParamThatDoesNotExist", buffer, sizeof(buffer), &out_len));
3276 EXPECT_EQ(999u, out_len);
3277
3278 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(mark, "Position", buffer,
3279 sizeof(buffer), nullptr));
3280
3281 page_object = FPDFPage_GetObject(page, 8);
3282 mark = FPDFPageObj_GetMark(page_object, 0);
3283 out_len = 999u;
3284 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(mark, "Factor", buffer,
3285 sizeof(buffer), &out_len));
3286 EXPECT_EQ(999u, out_len);
3287
3288 UnloadPage(page);
3289}
3290
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003291TEST_F(FPDFEditEmbedderTest, GetBitmap) {
Jane Liu28fb7ba2017-08-02 21:45:57 -04003292 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3293 FPDF_PAGE page = LoadPage(0);
3294 ASSERT_TRUE(page);
Miklos Vajna92627612017-09-25 12:59:29 +02003295 ASSERT_EQ(39, FPDFPage_CountObjects(page));
Jane Liu28fb7ba2017-08-02 21:45:57 -04003296
3297 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 32);
3298 EXPECT_NE(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3299 EXPECT_FALSE(FPDFImageObj_GetBitmap(obj));
3300
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003301 {
3302 obj = FPDFPage_GetObject(page, 33);
3303 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3304 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3305 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
Lei Zhang85166512020-07-14 23:28:56 +00003306 CompareBitmap(bitmap.get(), 109, 88, kEmbeddedImage33Checksum);
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003307 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003308
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003309 {
3310 obj = FPDFPage_GetObject(page, 34);
3311 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3312 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3313 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3314 CompareBitmap(bitmap.get(), 103, 75, "c8d51fa6821ceb2a67f08446ff236c40");
3315 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003316
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003317 {
3318 obj = FPDFPage_GetObject(page, 35);
3319 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3320 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3321 EXPECT_EQ(FPDFBitmap_Gray, FPDFBitmap_GetFormat(bitmap.get()));
3322 CompareBitmap(bitmap.get(), 92, 68, "9c6d76cb1e37ef8514f9455d759391f3");
3323 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003324
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003325 {
3326 obj = FPDFPage_GetObject(page, 36);
3327 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3328 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3329 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3330 CompareBitmap(bitmap.get(), 79, 60, "f4e72fb783a01c7b4614cdc25eaa98ac");
3331 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003332
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003333 {
3334 obj = FPDFPage_GetObject(page, 37);
3335 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3336 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3337 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3338 CompareBitmap(bitmap.get(), 126, 106, "2cf9e66414c72461f4ccbf9cdebdfa1b");
3339 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003340
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003341 {
3342 obj = FPDFPage_GetObject(page, 38);
3343 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3344 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3345 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3346 CompareBitmap(bitmap.get(), 194, 119, "a8f3a126cec274dab8242fd2ccdc1b8b");
3347 }
3348
Jane Liu28fb7ba2017-08-02 21:45:57 -04003349 UnloadPage(page);
3350}
Jane Liu548334e2017-08-03 16:33:40 -04003351
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003352TEST_F(FPDFEditEmbedderTest, GetBitmapIgnoresSetMatrix) {
Lei Zhang85166512020-07-14 23:28:56 +00003353 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3354 FPDF_PAGE page = LoadPage(0);
3355 ASSERT_TRUE(page);
3356 ASSERT_EQ(39, FPDFPage_CountObjects(page));
3357
3358 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3359 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3360
3361 {
3362 // Render |obj| as is.
3363 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3364 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3365 CompareBitmap(bitmap.get(), 109, 88, kEmbeddedImage33Checksum);
3366 }
3367
3368 // Check the matrix for |obj|.
3369 double a;
3370 double b;
3371 double c;
3372 double d;
3373 double e;
3374 double f;
3375 EXPECT_TRUE(FPDFImageObj_GetMatrix(obj, &a, &b, &c, &d, &e, &f));
3376 EXPECT_DOUBLE_EQ(53.0, a);
3377 EXPECT_DOUBLE_EQ(0.0, b);
3378 EXPECT_DOUBLE_EQ(0.0, c);
3379 EXPECT_DOUBLE_EQ(43.0, d);
3380 EXPECT_DOUBLE_EQ(72.0, e);
3381 EXPECT_DOUBLE_EQ(646.510009765625, f);
3382
3383 // Modify the matrix for |obj|.
3384 a = 120.0;
3385 EXPECT_TRUE(FPDFImageObj_SetMatrix(obj, a, b, c, d, e, f));
3386
3387 // Make sure the matrix modification took place.
3388 EXPECT_TRUE(FPDFImageObj_GetMatrix(obj, &a, &b, &c, &d, &e, &f));
3389 EXPECT_DOUBLE_EQ(120.0, a);
3390 EXPECT_DOUBLE_EQ(0.0, b);
3391 EXPECT_DOUBLE_EQ(0.0, c);
3392 EXPECT_DOUBLE_EQ(43.0, d);
3393 EXPECT_DOUBLE_EQ(72.0, e);
3394 EXPECT_DOUBLE_EQ(646.510009765625, f);
3395
3396 {
3397 // Render |obj| again. Note that the FPDFImageObj_SetMatrix() call has no
3398 // effect.
3399 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3400 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3401 CompareBitmap(bitmap.get(), 109, 88, kEmbeddedImage33Checksum);
3402 }
3403
3404 UnloadPage(page);
3405}
3406
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003407TEST_F(FPDFEditEmbedderTest, GetBitmapForJBigImage) {
Lei Zhang53341dd2018-03-01 15:42:47 +00003408 ASSERT_TRUE(OpenDocument("bug_631912.pdf"));
3409 FPDF_PAGE page = LoadPage(0);
3410 ASSERT_TRUE(page);
3411 ASSERT_EQ(1, FPDFPage_CountObjects(page));
3412
3413 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
3414 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3415 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00003416 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
Lei Zhang1330ebb2018-03-05 15:16:37 +00003417 ASSERT_TRUE(bitmap);
3418 EXPECT_EQ(FPDFBitmap_Gray, FPDFBitmap_GetFormat(bitmap.get()));
3419 CompareBitmap(bitmap.get(), 1152, 720, "3f6a48e2b3e91b799bf34567f55cb4de");
Lei Zhang53341dd2018-03-01 15:42:47 +00003420 }
3421
3422 UnloadPage(page);
3423}
3424
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003425TEST_F(FPDFEditEmbedderTest, GetBitmapIgnoresSMask) {
Lei Zhang2e1b4f22020-07-08 23:40:18 +00003426 ASSERT_TRUE(OpenDocument("matte.pdf"));
3427 FPDF_PAGE page = LoadPage(0);
3428 ASSERT_TRUE(page);
3429
3430 constexpr int kExpectedObjects = 4;
3431 ASSERT_EQ(kExpectedObjects, FPDFPage_CountObjects(page));
3432
3433 for (int i = 0; i < kExpectedObjects; ++i) {
3434 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, i);
3435 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3436 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3437 ASSERT_TRUE(bitmap);
3438 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3439 CompareBitmap(bitmap.get(), 50, 50, "46c9a1dbe0b44765ce46017ad629a2fe");
3440 }
3441
3442 UnloadPage(page);
3443}
3444
Hui Yingst822fb8d2020-10-05 22:10:35 +00003445// TODO(crbug.com/pdfium/11): Fix this test and enable.
3446#if defined(_SKIA_SUPPORT_)
3447#define MAYBE_GetRenderedBitmapHandlesSetMatrix \
3448 DISABLED_GetRenderedBitmapHandlesSetMatrix
3449#else
3450#define MAYBE_GetRenderedBitmapHandlesSetMatrix \
3451 GetRenderedBitmapHandlesSetMatrix
3452#endif
3453TEST_F(FPDFEditEmbedderTest, MAYBE_GetRenderedBitmapHandlesSetMatrix) {
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003454 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3455 FPDF_PAGE page = LoadPage(0);
3456 ASSERT_TRUE(page);
3457 ASSERT_EQ(39, FPDFPage_CountObjects(page));
3458
3459 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3460 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3461
3462 {
3463 // Render |obj| as is.
3464 ScopedFPDFBitmap bitmap(
3465 FPDFImageObj_GetRenderedBitmap(document(), page, obj));
3466 EXPECT_EQ(FPDFBitmap_BGRA, FPDFBitmap_GetFormat(bitmap.get()));
3467 CompareBitmap(bitmap.get(), 53, 43, "90fa16c2fb2bf8ad3654c2258417664c");
3468 }
3469
3470 // Check the matrix for |obj|.
3471 double a;
3472 double b;
3473 double c;
3474 double d;
3475 double e;
3476 double f;
3477 EXPECT_TRUE(FPDFImageObj_GetMatrix(obj, &a, &b, &c, &d, &e, &f));
3478 EXPECT_DOUBLE_EQ(53.0, a);
3479 EXPECT_DOUBLE_EQ(0.0, b);
3480 EXPECT_DOUBLE_EQ(0.0, c);
3481 EXPECT_DOUBLE_EQ(43.0, d);
3482 EXPECT_DOUBLE_EQ(72.0, e);
3483 EXPECT_DOUBLE_EQ(646.510009765625, f);
3484
3485 // Modify the matrix for |obj|.
3486 a = 120.0;
3487 EXPECT_TRUE(FPDFImageObj_SetMatrix(obj, a, b, c, d, e, f));
3488
3489 // Make sure the matrix modification took place.
3490 EXPECT_TRUE(FPDFImageObj_GetMatrix(obj, &a, &b, &c, &d, &e, &f));
3491 EXPECT_DOUBLE_EQ(120.0, a);
3492 EXPECT_DOUBLE_EQ(0.0, b);
3493 EXPECT_DOUBLE_EQ(0.0, c);
3494 EXPECT_DOUBLE_EQ(43.0, d);
3495 EXPECT_DOUBLE_EQ(72.0, e);
3496 EXPECT_DOUBLE_EQ(646.510009765625, f);
3497
3498 {
3499 // Render |obj| again. Note that the FPDFImageObj_SetMatrix() call has an
3500 // effect.
3501 ScopedFPDFBitmap bitmap(
3502 FPDFImageObj_GetRenderedBitmap(document(), page, obj));
3503 EXPECT_EQ(FPDFBitmap_BGRA, FPDFBitmap_GetFormat(bitmap.get()));
3504 CompareBitmap(bitmap.get(), 120, 43, "57ed8e15daa535490ff0c8b7640a36b4");
3505 }
3506
3507 UnloadPage(page);
3508}
3509
Hui Yingst822fb8d2020-10-05 22:10:35 +00003510// TODO(crbug.com/pdfium/11): Fix this test and enable.
3511#if defined(_SKIA_SUPPORT_)
3512#define MAYBE_GetRenderedBitmapHandlesSMask \
3513 DISABLED_GetRenderedBitmapHandlesSMask
3514#else
3515#define MAYBE_GetRenderedBitmapHandlesSMask GetRenderedBitmapHandlesSMask
3516#endif
3517TEST_F(FPDFEditEmbedderTest, MAYBE_GetRenderedBitmapHandlesSMask) {
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003518 ASSERT_TRUE(OpenDocument("matte.pdf"));
3519 FPDF_PAGE page = LoadPage(0);
3520 ASSERT_TRUE(page);
3521
3522 constexpr int kExpectedObjects = 4;
3523 ASSERT_EQ(kExpectedObjects, FPDFPage_CountObjects(page));
3524
3525 for (int i = 0; i < kExpectedObjects; ++i) {
3526 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, i);
3527 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3528 ScopedFPDFBitmap bitmap(
3529 FPDFImageObj_GetRenderedBitmap(document(), page, obj));
3530 ASSERT_TRUE(bitmap);
3531 EXPECT_EQ(FPDFBitmap_BGRA, FPDFBitmap_GetFormat(bitmap.get()));
3532 if (i == 0)
3533 CompareBitmap(bitmap.get(), 40, 60, "5a3ae4a660ce919e29c42ec2258142f1");
3534 else
3535 CompareBitmap(bitmap.get(), 40, 60, "67504e83f5d78214ea00efc19082c5c1");
3536 }
3537
3538 UnloadPage(page);
3539}
3540
3541TEST_F(FPDFEditEmbedderTest, GetRenderedBitmapBadParams) {
3542 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3543 FPDF_PAGE page = LoadPage(0);
3544 ASSERT_TRUE(page);
3545
3546 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3547 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3548
3549 // Test various null parameters.
3550 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, nullptr, nullptr));
3551 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(document(), nullptr, nullptr));
3552 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, page, nullptr));
3553 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, nullptr, obj));
3554 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(document(), page, nullptr));
3555 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, page, obj));
3556
3557 // Test mismatch between document and page parameters.
3558 ScopedFPDFDocument new_document(FPDF_CreateNewDocument());
3559 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(new_document.get(), page, obj));
3560
3561 UnloadPage(page);
3562}
3563
Lei Zhangab41f252018-12-23 03:10:50 +00003564TEST_F(FPDFEditEmbedderTest, GetImageData) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003565 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
Jane Liu548334e2017-08-03 16:33:40 -04003566 FPDF_PAGE page = LoadPage(0);
3567 ASSERT_TRUE(page);
Miklos Vajna92627612017-09-25 12:59:29 +02003568 ASSERT_EQ(39, FPDFPage_CountObjects(page));
Jane Liu548334e2017-08-03 16:33:40 -04003569
3570 // Retrieve an image object with flate-encoded data stream.
3571 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3572 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3573
3574 // Check that the raw image data has the correct length and hash value.
3575 unsigned long len = FPDFImageObj_GetImageDataRaw(obj, nullptr, 0);
3576 std::vector<char> buf(len);
3577 EXPECT_EQ(4091u, FPDFImageObj_GetImageDataRaw(obj, buf.data(), len));
3578 EXPECT_EQ("f73802327d2e88e890f653961bcda81a",
3579 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3580
3581 // Check that the decoded image data has the correct length and hash value.
3582 len = FPDFImageObj_GetImageDataDecoded(obj, nullptr, 0);
3583 buf.clear();
3584 buf.resize(len);
3585 EXPECT_EQ(28776u, FPDFImageObj_GetImageDataDecoded(obj, buf.data(), len));
Lei Zhang85166512020-07-14 23:28:56 +00003586 EXPECT_EQ(kEmbeddedImage33Checksum,
Jane Liu548334e2017-08-03 16:33:40 -04003587 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3588
Lei Zhang351e8b02018-12-20 01:10:06 +00003589 // Retrieve an image object with DCTDecode-encoded data stream.
Jane Liu548334e2017-08-03 16:33:40 -04003590 obj = FPDFPage_GetObject(page, 37);
3591 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3592
3593 // Check that the raw image data has the correct length and hash value.
3594 len = FPDFImageObj_GetImageDataRaw(obj, nullptr, 0);
3595 buf.clear();
3596 buf.resize(len);
3597 EXPECT_EQ(4370u, FPDFImageObj_GetImageDataRaw(obj, buf.data(), len));
3598 EXPECT_EQ("6aae1f3710335023a9e12191be66b64b",
3599 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3600
3601 // Check that the decoded image data has the correct length and hash value,
3602 // which should be the same as those of the raw data, since this image is
3603 // encoded by a single DCTDecode filter and decoding is a noop.
3604 len = FPDFImageObj_GetImageDataDecoded(obj, nullptr, 0);
3605 buf.clear();
3606 buf.resize(len);
3607 EXPECT_EQ(4370u, FPDFImageObj_GetImageDataDecoded(obj, buf.data(), len));
3608 EXPECT_EQ("6aae1f3710335023a9e12191be66b64b",
3609 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3610
3611 UnloadPage(page);
3612}
Jane Liu2e5f0ae2017-08-08 15:23:27 -04003613
Lei Zhangab41f252018-12-23 03:10:50 +00003614TEST_F(FPDFEditEmbedderTest, GetImageMatrix) {
Lei Zhang866d6882018-10-24 17:31:01 +00003615 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3616 FPDF_PAGE page = LoadPage(0);
3617 ASSERT_TRUE(page);
3618 ASSERT_EQ(39, FPDFPage_CountObjects(page));
3619
3620 FPDF_PAGEOBJECT obj;
3621 double a;
3622 double b;
3623 double c;
3624 double d;
3625 double e;
3626 double f;
3627
3628 obj = FPDFPage_GetObject(page, 33);
3629 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3630 EXPECT_TRUE(FPDFImageObj_GetMatrix(obj, &a, &b, &c, &d, &e, &f));
3631 EXPECT_DOUBLE_EQ(53.0, a);
3632 EXPECT_DOUBLE_EQ(0.0, b);
3633 EXPECT_DOUBLE_EQ(0.0, c);
3634 EXPECT_DOUBLE_EQ(43.0, d);
3635 EXPECT_DOUBLE_EQ(72.0, e);
3636 EXPECT_DOUBLE_EQ(646.510009765625, f);
3637
3638 obj = FPDFPage_GetObject(page, 34);
3639 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3640 EXPECT_TRUE(FPDFImageObj_GetMatrix(obj, &a, &b, &c, &d, &e, &f));
3641 EXPECT_DOUBLE_EQ(70.0, a);
3642 EXPECT_DOUBLE_EQ(0.0, b);
3643 EXPECT_DOUBLE_EQ(0.0, c);
3644 EXPECT_DOUBLE_EQ(51.0, d);
3645 EXPECT_DOUBLE_EQ(216.0, e);
3646 EXPECT_DOUBLE_EQ(646.510009765625, f);
3647
3648 obj = FPDFPage_GetObject(page, 35);
3649 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3650 EXPECT_TRUE(FPDFImageObj_GetMatrix(obj, &a, &b, &c, &d, &e, &f));
3651 EXPECT_DOUBLE_EQ(69.0, a);
3652 EXPECT_DOUBLE_EQ(0.0, b);
3653 EXPECT_DOUBLE_EQ(0.0, c);
3654 EXPECT_DOUBLE_EQ(51.0, d);
3655 EXPECT_DOUBLE_EQ(360.0, e);
3656 EXPECT_DOUBLE_EQ(646.510009765625, f);
3657
3658 obj = FPDFPage_GetObject(page, 36);
3659 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3660 EXPECT_TRUE(FPDFImageObj_GetMatrix(obj, &a, &b, &c, &d, &e, &f));
3661 EXPECT_DOUBLE_EQ(59.0, a);
3662 EXPECT_DOUBLE_EQ(0.0, b);
3663 EXPECT_DOUBLE_EQ(0.0, c);
3664 EXPECT_DOUBLE_EQ(45.0, d);
3665 EXPECT_DOUBLE_EQ(72.0, e);
3666 EXPECT_DOUBLE_EQ(553.510009765625, f);
3667
3668 obj = FPDFPage_GetObject(page, 37);
3669 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3670 EXPECT_TRUE(FPDFImageObj_GetMatrix(obj, &a, &b, &c, &d, &e, &f));
3671 EXPECT_DOUBLE_EQ(55.94000244140625, a);
3672 EXPECT_DOUBLE_EQ(0.0, b);
3673 EXPECT_DOUBLE_EQ(0.0, c);
3674 EXPECT_DOUBLE_EQ(46.950000762939453, d);
3675 EXPECT_DOUBLE_EQ(216.0, e);
3676 EXPECT_DOUBLE_EQ(552.510009765625, f);
3677
3678 obj = FPDFPage_GetObject(page, 38);
3679 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3680 EXPECT_TRUE(FPDFImageObj_GetMatrix(obj, &a, &b, &c, &d, &e, &f));
3681 EXPECT_DOUBLE_EQ(70.528999328613281, a);
3682 EXPECT_DOUBLE_EQ(0.0, b);
3683 EXPECT_DOUBLE_EQ(0.0, c);
3684 EXPECT_DOUBLE_EQ(43.149997711181641, d);
3685 EXPECT_DOUBLE_EQ(360.0, e);
3686 EXPECT_DOUBLE_EQ(553.3599853515625, f);
3687
3688 UnloadPage(page);
3689}
3690
Lei Zhangab41f252018-12-23 03:10:50 +00003691TEST_F(FPDFEditEmbedderTest, DestroyPageObject) {
Jane Liu2e5f0ae2017-08-08 15:23:27 -04003692 FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
3693 ASSERT_TRUE(rect);
3694
3695 // There should be no memory leaks with a call to FPDFPageObj_Destroy().
3696 FPDFPageObj_Destroy(rect);
3697}
Jane Liube63ab92017-08-09 14:09:34 -04003698
Lei Zhangab41f252018-12-23 03:10:50 +00003699TEST_F(FPDFEditEmbedderTest, GetImageFilters) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003700 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
Jane Liube63ab92017-08-09 14:09:34 -04003701 FPDF_PAGE page = LoadPage(0);
3702 ASSERT_TRUE(page);
3703
3704 // Verify that retrieving the filter of a non-image object would fail.
3705 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 32);
3706 ASSERT_NE(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3707 ASSERT_EQ(0, FPDFImageObj_GetImageFilterCount(obj));
3708 EXPECT_EQ(0u, FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0));
3709
3710 // Verify the returned filter string for an image object with a single filter.
3711 obj = FPDFPage_GetObject(page, 33);
3712 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3713 ASSERT_EQ(1, FPDFImageObj_GetImageFilterCount(obj));
3714 unsigned long len = FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0);
3715 std::vector<char> buf(len);
Lei Zhang0733a1b2017-08-31 12:36:31 -07003716 static constexpr char kFlateDecode[] = "FlateDecode";
3717 EXPECT_EQ(sizeof(kFlateDecode),
3718 FPDFImageObj_GetImageFilter(obj, 0, buf.data(), len));
3719 EXPECT_STREQ(kFlateDecode, buf.data());
Jane Liube63ab92017-08-09 14:09:34 -04003720 EXPECT_EQ(0u, FPDFImageObj_GetImageFilter(obj, 1, nullptr, 0));
3721
3722 // Verify all the filters for an image object with a list of filters.
3723 obj = FPDFPage_GetObject(page, 38);
3724 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3725 ASSERT_EQ(2, FPDFImageObj_GetImageFilterCount(obj));
3726 len = FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0);
3727 buf.clear();
3728 buf.resize(len);
Lei Zhang0733a1b2017-08-31 12:36:31 -07003729 static constexpr char kASCIIHexDecode[] = "ASCIIHexDecode";
3730 EXPECT_EQ(sizeof(kASCIIHexDecode),
3731 FPDFImageObj_GetImageFilter(obj, 0, buf.data(), len));
3732 EXPECT_STREQ(kASCIIHexDecode, buf.data());
Jane Liube63ab92017-08-09 14:09:34 -04003733
3734 len = FPDFImageObj_GetImageFilter(obj, 1, nullptr, 0);
3735 buf.clear();
3736 buf.resize(len);
Lei Zhang0733a1b2017-08-31 12:36:31 -07003737 static constexpr char kDCTDecode[] = "DCTDecode";
3738 EXPECT_EQ(sizeof(kDCTDecode),
3739 FPDFImageObj_GetImageFilter(obj, 1, buf.data(), len));
3740 EXPECT_STREQ(kDCTDecode, buf.data());
Jane Liube63ab92017-08-09 14:09:34 -04003741
3742 UnloadPage(page);
3743}
Jane Liuca898292017-08-16 11:25:35 -04003744
Lei Zhangab41f252018-12-23 03:10:50 +00003745TEST_F(FPDFEditEmbedderTest, GetImageMetadata) {
Jane Liuca898292017-08-16 11:25:35 -04003746 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3747 FPDF_PAGE page = LoadPage(0);
3748 ASSERT_TRUE(page);
3749
3750 // Check that getting the metadata of a null object would fail.
3751 FPDF_IMAGEOBJ_METADATA metadata;
3752 EXPECT_FALSE(FPDFImageObj_GetImageMetadata(nullptr, page, &metadata));
3753
3754 // Check that receiving the metadata with a null metadata object would fail.
3755 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 35);
3756 EXPECT_FALSE(FPDFImageObj_GetImageMetadata(obj, page, nullptr));
3757
3758 // Check that when retrieving an image object's metadata without passing in
3759 // |page|, all values are correct, with the last two being default values.
3760 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3761 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, nullptr, &metadata));
Julian Lungerecd063e2017-12-27 10:18:50 -05003762 EXPECT_EQ(7, metadata.marked_content_id);
Jane Liuca898292017-08-16 11:25:35 -04003763 EXPECT_EQ(92u, metadata.width);
3764 EXPECT_EQ(68u, metadata.height);
Lei Zhang351e8b02018-12-20 01:10:06 +00003765 EXPECT_FLOAT_EQ(96.0f, metadata.horizontal_dpi);
3766 EXPECT_FLOAT_EQ(96.0f, metadata.vertical_dpi);
Jane Liuca898292017-08-16 11:25:35 -04003767 EXPECT_EQ(0u, metadata.bits_per_pixel);
3768 EXPECT_EQ(FPDF_COLORSPACE_UNKNOWN, metadata.colorspace);
3769
3770 // Verify the metadata of a bitmap image with indexed colorspace.
3771 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata));
Julian Lungerecd063e2017-12-27 10:18:50 -05003772 EXPECT_EQ(7, metadata.marked_content_id);
Jane Liuca898292017-08-16 11:25:35 -04003773 EXPECT_EQ(92u, metadata.width);
3774 EXPECT_EQ(68u, metadata.height);
Lei Zhang351e8b02018-12-20 01:10:06 +00003775 EXPECT_FLOAT_EQ(96.0f, metadata.horizontal_dpi);
3776 EXPECT_FLOAT_EQ(96.0f, metadata.vertical_dpi);
Jane Liuca898292017-08-16 11:25:35 -04003777 EXPECT_EQ(1u, metadata.bits_per_pixel);
3778 EXPECT_EQ(FPDF_COLORSPACE_INDEXED, metadata.colorspace);
3779
3780 // Verify the metadata of an image with RGB colorspace.
3781 obj = FPDFPage_GetObject(page, 37);
3782 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3783 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata));
Julian Lungerecd063e2017-12-27 10:18:50 -05003784 EXPECT_EQ(9, metadata.marked_content_id);
Jane Liuca898292017-08-16 11:25:35 -04003785 EXPECT_EQ(126u, metadata.width);
3786 EXPECT_EQ(106u, metadata.height);
Lei Zhang351e8b02018-12-20 01:10:06 +00003787 EXPECT_FLOAT_EQ(162.173752f, metadata.horizontal_dpi);
3788 EXPECT_FLOAT_EQ(162.555878f, metadata.vertical_dpi);
Jane Liuca898292017-08-16 11:25:35 -04003789 EXPECT_EQ(24u, metadata.bits_per_pixel);
3790 EXPECT_EQ(FPDF_COLORSPACE_DEVICERGB, metadata.colorspace);
3791
3792 UnloadPage(page);
3793}
Lei Zhangdc1b7392020-05-14 21:15:53 +00003794
3795TEST_F(FPDFEditEmbedderTest, GetImageMetadataJpxLzw) {
3796 ASSERT_TRUE(OpenDocument("jpx_lzw.pdf"));
3797 FPDF_PAGE page = LoadPage(0);
3798 ASSERT_TRUE(page);
3799
3800 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
3801 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3802
3803 FPDF_IMAGEOBJ_METADATA metadata;
3804 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata));
3805 EXPECT_EQ(-1, metadata.marked_content_id);
3806 EXPECT_EQ(612u, metadata.width);
3807 EXPECT_EQ(792u, metadata.height);
3808 EXPECT_FLOAT_EQ(72.0f, metadata.horizontal_dpi);
3809 EXPECT_FLOAT_EQ(72.0f, metadata.vertical_dpi);
3810 EXPECT_EQ(24u, metadata.bits_per_pixel);
3811 EXPECT_EQ(FPDF_COLORSPACE_UNKNOWN, metadata.colorspace);
3812
3813 UnloadPage(page);
3814}