blob: de213c76098d28504b0c78a30b69f02db881d4a5 [file] [log] [blame]
Tom Sepezd483eb42016-01-06 10:03:59 -08001// Copyright 2016 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Dan Sinclair85c8e7f2016-11-21 13:50:32 -05005#include <memory>
6#include <string>
Nicolas Penad03ca422017-03-06 13:54:33 -05007#include <utility>
Jane Liu548334e2017-08-03 16:33:40 -04008#include <vector>
Dan Sinclair85c8e7f2016-11-21 13:50:32 -05009
Lei Zhange4cdac52019-04-30 16:45:57 +000010#include "build/build_config.h"
Nicolas Penabe90aae2017-02-27 10:41:41 -050011#include "core/fpdfapi/font/cpdf_font.h"
Nicolas Penaa4ad01f2017-02-15 16:26:48 -050012#include "core/fpdfapi/page/cpdf_page.h"
Henrique Nakashima6eb79392018-06-12 20:27:35 +000013#include "core/fpdfapi/page/cpdf_pageobject.h"
Nicolas Penabe90aae2017-02-27 10:41:41 -050014#include "core/fpdfapi/parser/cpdf_array.h"
Nicolas Penaa4ad01f2017-02-15 16:26:48 -050015#include "core/fpdfapi/parser/cpdf_dictionary.h"
Nicolas Penad03ca422017-03-06 13:54:33 -050016#include "core/fpdfapi/parser/cpdf_number.h"
Nicolas Penabe90aae2017-02-27 10:41:41 -050017#include "core/fpdfapi/parser/cpdf_stream.h"
Artem Strygineababa12018-06-06 12:31:18 +000018#include "core/fpdfapi/parser/cpdf_stream_acc.h"
Tom Sepez6c57cda2021-07-23 19:41:57 +000019#include "core/fxcrt/fx_codepage.h"
Nicolas Pena0fc185e2017-02-08 12:13:20 -050020#include "core/fxcrt/fx_system.h"
Lei Zhang0dcb8fd2019-02-07 00:46:04 +000021#include "core/fxge/fx_font.h"
Dan Sinclair00d47a62018-03-28 18:39:04 +000022#include "fpdfsdk/cpdfsdk_helpers.h"
Tom Sepeze08d2b12018-04-25 18:49:32 +000023#include "public/cpp/fpdf_scopers.h"
Jane Liueda65252017-06-07 11:31:27 -040024#include "public/fpdf_annot.h"
Tom Sepezd483eb42016-01-06 10:03:59 -080025#include "public/fpdf_edit.h"
26#include "public/fpdfview.h"
27#include "testing/embedder_test.h"
Hui Yingstb4baceb2020-04-28 23:46:10 +000028#include "testing/embedder_test_constants.h"
Lei Zhangb6992dd2019-02-05 23:30:20 +000029#include "testing/fx_string_testhelpers.h"
Tom Sepez0aec19b2016-01-07 12:22:44 -080030#include "testing/gmock/include/gmock/gmock-matchers.h"
Tom Sepezd483eb42016-01-06 10:03:59 -080031#include "testing/gtest/include/gtest/gtest.h"
Hui Yingst8e88e382020-11-02 18:19:56 +000032#include "testing/utils/file_util.h"
Lei Zhang4c64e962019-02-05 19:24:12 +000033#include "testing/utils/hash.h"
Hui Yingst8e88e382020-11-02 18:19:56 +000034#include "testing/utils/path_service.h"
Tom Sepez9c78c0d2021-01-27 20:13:14 +000035#include "third_party/base/check.h"
Tom Sepezd483eb42016-01-06 10:03:59 -080036
Hui Yingstb4baceb2020-04-28 23:46:10 +000037using pdfium::kHelloWorldChecksum;
38
39namespace {
40
Hui Yingst3b6136a2020-06-09 00:39:33 +000041const char kAllRemovedChecksum[] = "eee4600ac08b458ac7ac2320e225674c";
42
43const wchar_t kBottomText[] = L"I'm at the bottom of the page";
44
Hui Yingst5ce6a3f2020-11-11 02:29:09 +000045#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
46static constexpr char kBottomTextChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +000047 "84461cd5d952b6ae3d57a5070da84e19";
Lei Zhang42d30c22022-01-12 19:24:43 +000048#elif BUILDFLAG(IS_APPLE)
Hui Yingst5ce6a3f2020-11-11 02:29:09 +000049static constexpr char kBottomTextChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +000050 "81636489006a31fcb00cf29efcdf7909";
Hui Yingst5ce6a3f2020-11-11 02:29:09 +000051#else
52static constexpr char kBottomTextChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +000053 "891dcb6e914c8360998055f1f47c9727";
Hui Yingst3b6136a2020-06-09 00:39:33 +000054#endif
Hui Yingstb4baceb2020-04-28 23:46:10 +000055
Hui Yingst08c40712020-04-29 01:37:35 +000056#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +000057const char kFirstRemovedChecksum[] = "f46cbf12eb4e9bbdc3a5d8e1f2103446";
Lei Zhang42d30c22022-01-12 19:24:43 +000058#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +000059const char kFirstRemovedChecksum[] = "a1dc2812692fcc7ee4f01ca77435df9d";
Hui Yingstb4baceb2020-04-28 23:46:10 +000060#else
Tom Andersond4fe5f72021-12-03 20:52:52 +000061const char kFirstRemovedChecksum[] = "e1477dc3b5b3b9c560814c4d1135a02b";
Hui Yingstb4baceb2020-04-28 23:46:10 +000062#endif
63
Hui Yingst3b6136a2020-06-09 00:39:33 +000064const wchar_t kLoadedFontText[] = L"I am testing my loaded font, WEE.";
65
Hui Yingst9d6ec8f2020-11-05 23:35:38 +000066#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +000067const char kLoadedFontTextChecksum[] = "fc2334c350cbd0d2ae6076689da09741";
Lei Zhang42d30c22022-01-12 19:24:43 +000068#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +000069const char kLoadedFontTextChecksum[] = "0f3e4a7d71f9e7eb8a1a0d69403b9848";
Hui Yingst3b6136a2020-06-09 00:39:33 +000070#else
Tom Andersond4fe5f72021-12-03 20:52:52 +000071const char kLoadedFontTextChecksum[] = "d58570cc045dfb818b92cbabbd1a364c";
Hui Yingst3b6136a2020-06-09 00:39:33 +000072#endif
73
74const char kRedRectangleChecksum[] = "66d02eaa6181e2c069ce2ea99beda497";
75
Lei Zhang85166512020-07-14 23:28:56 +000076// In embedded_images.pdf.
77const char kEmbeddedImage33Checksum[] = "cb3637934bb3b95a6e4ae1ea9eb9e56e";
78
Hui Yingstb4baceb2020-04-28 23:46:10 +000079} // namespace
80
Lei Zhangab41f252018-12-23 03:10:50 +000081class FPDFEditEmbedderTest : public EmbedderTest {
Nicolas Penad03ca422017-03-06 13:54:33 -050082 protected:
83 FPDF_DOCUMENT CreateNewDocument() {
Lei Zhang935fb862021-11-05 00:15:05 +000084 CreateEmptyDocumentWithoutFormFillEnvironment();
Lei Zhang38e2b0e2021-11-05 00:28:05 +000085 cpdf_doc_ = CPDFDocumentFromFPDFDocument(document());
86 return document();
Nicolas Penad03ca422017-03-06 13:54:33 -050087 }
88
Lei Zhang710fa992018-05-25 16:24:48 +000089 void CheckFontDescriptor(const CPDF_Dictionary* font_dict,
Nicolas Penad03ca422017-03-06 13:54:33 -050090 int font_type,
91 bool bold,
92 bool italic,
Tom Sepez20c41a52018-08-29 23:53:53 +000093 pdfium::span<const uint8_t> span) {
Lei Zhangb1ec2802018-05-25 21:55:24 +000094 const CPDF_Dictionary* font_desc = font_dict->GetDictFor("FontDescriptor");
Nicolas Penad03ca422017-03-06 13:54:33 -050095 ASSERT_TRUE(font_desc);
Lei Zhanga228ff32020-06-24 17:39:33 +000096 EXPECT_EQ("FontDescriptor", font_desc->GetNameFor("Type"));
97 ByteString font_name = font_desc->GetNameFor("FontName");
98 EXPECT_FALSE(font_name.IsEmpty());
99 EXPECT_EQ(font_dict->GetNameFor("BaseFont"), font_name);
Nicolas Penad03ca422017-03-06 13:54:33 -0500100
101 // Check that the font descriptor has the required keys according to spec
102 // 1.7 Table 5.19
103 ASSERT_TRUE(font_desc->KeyExist("Flags"));
Dan Sinclair10e1f052017-09-28 15:59:42 -0400104
Nicolas Penad03ca422017-03-06 13:54:33 -0500105 int font_flags = font_desc->GetIntegerFor("Flags");
Lei Zhang44d03832019-10-18 18:45:31 +0000106 EXPECT_EQ(bold, FontStyleIsForceBold(font_flags));
Dan Sinclair10e1f052017-09-28 15:59:42 -0400107 EXPECT_EQ(italic, FontStyleIsItalic(font_flags));
108 EXPECT_TRUE(FontStyleIsNonSymbolic(font_flags));
Nicolas Penad03ca422017-03-06 13:54:33 -0500109 ASSERT_TRUE(font_desc->KeyExist("FontBBox"));
Nicolás Peña5f95f362017-09-28 13:00:45 +0900110
Lei Zhangb1ec2802018-05-25 21:55:24 +0000111 const CPDF_Array* fontBBox = font_desc->GetArrayFor("FontBBox");
Nicolás Peña5f95f362017-09-28 13:00:45 +0900112 ASSERT_TRUE(fontBBox);
Lei Zhangf40380f2018-10-12 18:31:51 +0000113 EXPECT_EQ(4u, fontBBox->size());
Nicolás Peña5f95f362017-09-28 13:00:45 +0900114 // Check that the coordinates are in the preferred order according to spec
115 // 1.7 Section 3.8.4
116 EXPECT_TRUE(fontBBox->GetIntegerAt(0) < fontBBox->GetIntegerAt(2));
117 EXPECT_TRUE(fontBBox->GetIntegerAt(1) < fontBBox->GetIntegerAt(3));
118
Nicolas Penad03ca422017-03-06 13:54:33 -0500119 EXPECT_TRUE(font_desc->KeyExist("ItalicAngle"));
120 EXPECT_TRUE(font_desc->KeyExist("Ascent"));
121 EXPECT_TRUE(font_desc->KeyExist("Descent"));
122 EXPECT_TRUE(font_desc->KeyExist("CapHeight"));
123 EXPECT_TRUE(font_desc->KeyExist("StemV"));
Ryan Harrison275e2602017-09-18 14:23:18 -0400124 ByteString present("FontFile");
125 ByteString absent("FontFile2");
Nicolas Penad03ca422017-03-06 13:54:33 -0500126 if (font_type == FPDF_FONT_TRUETYPE)
127 std::swap(present, absent);
128 EXPECT_TRUE(font_desc->KeyExist(present));
129 EXPECT_FALSE(font_desc->KeyExist(absent));
130
Artem Strygineababa12018-06-06 12:31:18 +0000131 auto streamAcc =
132 pdfium::MakeRetain<CPDF_StreamAcc>(font_desc->GetStreamFor(present));
133 streamAcc->LoadAllDataRaw();
134
Nicolas Penad03ca422017-03-06 13:54:33 -0500135 // Check that the font stream is the one that was provided
Tom Sepez20c41a52018-08-29 23:53:53 +0000136 ASSERT_EQ(span.size(), streamAcc->GetSize());
Nicolás Peña79eab232017-09-28 13:29:05 +0900137 if (font_type == FPDF_FONT_TRUETYPE) {
Tom Sepez20c41a52018-08-29 23:53:53 +0000138 ASSERT_EQ(static_cast<int>(span.size()),
Artem Strygineababa12018-06-06 12:31:18 +0000139 streamAcc->GetDict()->GetIntegerFor("Length1"));
Nicolás Peña79eab232017-09-28 13:29:05 +0900140 }
Artem Strygineababa12018-06-06 12:31:18 +0000141
142 const uint8_t* stream_data = streamAcc->GetData();
Tom Sepez20c41a52018-08-29 23:53:53 +0000143 for (size_t j = 0; j < span.size(); j++)
144 EXPECT_EQ(span[j], stream_data[j]) << " at byte " << j;
Nicolas Penad03ca422017-03-06 13:54:33 -0500145 }
146
Lei Zhangde579ab2018-05-25 21:49:49 +0000147 void CheckCompositeFontWidths(const CPDF_Array* widths_array,
Nicolas Penad03ca422017-03-06 13:54:33 -0500148 CPDF_Font* typed_font) {
149 // Check that W array is in a format that conforms to PDF spec 1.7 section
150 // "Glyph Metrics in CIDFonts" (these checks are not
151 // implementation-specific).
Lei Zhangf40380f2018-10-12 18:31:51 +0000152 EXPECT_GT(widths_array->size(), 1u);
Nicolas Penad03ca422017-03-06 13:54:33 -0500153 int num_cids_checked = 0;
154 int cur_cid = 0;
Lei Zhangf40380f2018-10-12 18:31:51 +0000155 for (size_t idx = 0; idx < widths_array->size(); idx++) {
Nicolas Penad03ca422017-03-06 13:54:33 -0500156 int cid = widths_array->GetNumberAt(idx);
157 EXPECT_GE(cid, cur_cid);
Lei Zhangf40380f2018-10-12 18:31:51 +0000158 ASSERT_FALSE(++idx == widths_array->size());
Lei Zhangde579ab2018-05-25 21:49:49 +0000159 const CPDF_Object* next = widths_array->GetObjectAt(idx);
Nicolas Penad03ca422017-03-06 13:54:33 -0500160 if (next->IsArray()) {
161 // We are in the c [w1 w2 ...] case
Lei Zhangde579ab2018-05-25 21:49:49 +0000162 const CPDF_Array* arr = next->AsArray();
Lei Zhangf40380f2018-10-12 18:31:51 +0000163 int cnt = static_cast<int>(arr->size());
Nicolas Penad03ca422017-03-06 13:54:33 -0500164 size_t inner_idx = 0;
165 for (cur_cid = cid; cur_cid < cid + cnt; cur_cid++) {
Lei Zhang70e66192020-09-18 20:50:51 +0000166 int width = arr->GetNumberAt(inner_idx++);
Dan Sinclair971a6742018-03-28 19:23:25 +0000167 EXPECT_EQ(width, typed_font->GetCharWidthF(cur_cid))
168 << " at cid " << cur_cid;
Nicolas Penad03ca422017-03-06 13:54:33 -0500169 }
170 num_cids_checked += cnt;
171 continue;
172 }
173 // Otherwise, are in the c_first c_last w case.
174 ASSERT_TRUE(next->IsNumber());
175 int last_cid = next->AsNumber()->GetInteger();
Lei Zhangf40380f2018-10-12 18:31:51 +0000176 ASSERT_FALSE(++idx == widths_array->size());
Lei Zhang70e66192020-09-18 20:50:51 +0000177 int width = widths_array->GetNumberAt(idx);
Nicolas Penad03ca422017-03-06 13:54:33 -0500178 for (cur_cid = cid; cur_cid <= last_cid; cur_cid++) {
Dan Sinclair971a6742018-03-28 19:23:25 +0000179 EXPECT_EQ(width, typed_font->GetCharWidthF(cur_cid))
180 << " at cid " << cur_cid;
Nicolas Penad03ca422017-03-06 13:54:33 -0500181 }
182 num_cids_checked += last_cid - cid + 1;
183 }
184 // Make sure we have a good amount of cids described
Tom Andersond4fe5f72021-12-03 20:52:52 +0000185 EXPECT_GT(num_cids_checked, 200);
Nicolas Penad03ca422017-03-06 13:54:33 -0500186 }
187 CPDF_Document* cpdf_doc() { return cpdf_doc_; }
188
189 private:
190 CPDF_Document* cpdf_doc_;
191};
Tom Sepezd483eb42016-01-06 10:03:59 -0800192
etienneb7712c262016-04-26 08:13:45 -0700193namespace {
thestigdc7ec032016-11-21 15:32:52 -0800194
etienneb7712c262016-04-26 08:13:45 -0700195const char kExpectedPDF[] =
196 "%PDF-1.7\r\n"
197 "%\xA1\xB3\xC5\xD7\r\n"
198 "1 0 obj\r\n"
199 "<</Pages 2 0 R /Type/Catalog>>\r\n"
200 "endobj\r\n"
201 "2 0 obj\r\n"
202 "<</Count 1/Kids\\[ 4 0 R \\]/Type/Pages>>\r\n"
203 "endobj\r\n"
204 "3 0 obj\r\n"
205 "<</CreationDate\\(D:.*\\)/Creator\\(PDFium\\)>>\r\n"
206 "endobj\r\n"
207 "4 0 obj\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400208 "<</MediaBox\\[ 0 0 640 480\\]/Parent 2 0 R "
209 "/Resources<</ExtGState<</FXE1 5 0 R >>>>"
Nicolas Penad9d6c292017-06-06 16:12:10 -0400210 "/Rotate 0/Type/Page"
etienneb7712c262016-04-26 08:13:45 -0700211 ">>\r\n"
212 "endobj\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400213 "5 0 obj\r\n"
214 "<</BM/Normal/CA 1/ca 1>>\r\n"
215 "endobj\r\n"
etienneb7712c262016-04-26 08:13:45 -0700216 "xref\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400217 "0 6\r\n"
etienneb7712c262016-04-26 08:13:45 -0700218 "0000000000 65535 f\r\n"
219 "0000000017 00000 n\r\n"
220 "0000000066 00000 n\r\n"
221 "0000000122 00000 n\r\n"
222 "0000000192 00000 n\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400223 "0000000311 00000 n\r\n"
etienneb7712c262016-04-26 08:13:45 -0700224 "trailer\r\n"
225 "<<\r\n"
226 "/Root 1 0 R\r\n"
227 "/Info 3 0 R\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400228 "/Size 6/ID\\[<.*><.*>\\]>>\r\n"
etienneb7712c262016-04-26 08:13:45 -0700229 "startxref\r\n"
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -0400230 "354\r\n"
etienneb7712c262016-04-26 08:13:45 -0700231 "%%EOF\r\n";
thestigdc7ec032016-11-21 15:32:52 -0800232
etienneb7712c262016-04-26 08:13:45 -0700233} // namespace
234
Hui Yingst8e88e382020-11-02 18:19:56 +0000235TEST_F(FPDFEditEmbedderTest, EmbedNotoSansSCFont) {
Lei Zhangb8b4a042021-11-05 00:04:25 +0000236 CreateEmptyDocument();
Hui Yingst8e88e382020-11-02 18:19:56 +0000237 ScopedFPDFPage page(FPDFPage_New(document(), 0, 400, 400));
238 std::string font_path;
Hui Yingst8532ef02020-11-04 19:17:17 +0000239 ASSERT_TRUE(PathService::GetThirdPartyFilePath(
240 "NotoSansCJK/NotoSansSC-Regular.subset.otf", &font_path));
Hui Yingst8e88e382020-11-02 18:19:56 +0000241
242 size_t file_length = 0;
243 std::unique_ptr<char, pdfium::FreeDeleter> font_data =
244 GetFileContents(font_path.c_str(), &file_length);
Lei Zhang786544d2021-07-27 21:25:24 +0000245 ASSERT_TRUE(font_data);
Hui Yingst8e88e382020-11-02 18:19:56 +0000246
247 ScopedFPDFFont font(FPDFText_LoadFont(
248 document(), reinterpret_cast<const uint8_t*>(font_data.get()),
249 file_length, FPDF_FONT_TRUETYPE, /*cid=*/true));
250 FPDF_PAGEOBJECT text_object =
251 FPDFPageObj_CreateTextObj(document(), font.get(), 20.0f);
252 EXPECT_TRUE(text_object);
253
254 // Test the characters which are either mapped to one single unicode or
255 // multiple unicodes in the embedded font.
256 ScopedFPDFWideString text = GetFPDFWideString(L"这是第一句。 这是第二行。");
257 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
258
259 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 50, 200);
260 FPDFPage_InsertObject(page.get(), text_object);
261 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
262
263#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Lei Zhang42d30c22022-01-12 19:24:43 +0000264#if BUILDFLAG(IS_APPLE)
Hui Yingst8e88e382020-11-02 18:19:56 +0000265 const char kChecksum[] = "9a31fb87d1c6d2346bba22d1196041cd";
Lei Zhang42d30c22022-01-12 19:24:43 +0000266#else // BUILDFLAG(IS_APPLE)
Hui Yingst8e88e382020-11-02 18:19:56 +0000267 const char kChecksum[] = "5bb65e15fc0a685934cd5006dec08a76";
Lei Zhang42d30c22022-01-12 19:24:43 +0000268#endif // BUILDFLAG(IS_APPLE)
Lei Zhang786544d2021-07-27 21:25:24 +0000269#else // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Hui Yingst8e88e382020-11-02 18:19:56 +0000270 const char kChecksum[] = "9a31fb87d1c6d2346bba22d1196041cd";
Hui Yingst8e88e382020-11-02 18:19:56 +0000271#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
272 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
273 CompareBitmap(page_bitmap.get(), 400, 400, kChecksum);
274
Lei Zhang786544d2021-07-27 21:25:24 +0000275 ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
276 VerifySavedDocument(400, 400, kChecksum);
277}
278
279TEST_F(FPDFEditEmbedderTest, EmbedNotoSansSCFontWithCharcodes) {
Lei Zhangb8b4a042021-11-05 00:04:25 +0000280 CreateEmptyDocument();
Lei Zhang786544d2021-07-27 21:25:24 +0000281 ScopedFPDFPage page(FPDFPage_New(document(), 0, 400, 400));
282 std::string font_path;
283 ASSERT_TRUE(PathService::GetThirdPartyFilePath(
284 "NotoSansCJK/NotoSansSC-Regular.subset.otf", &font_path));
285
286 size_t file_length = 0;
287 std::unique_ptr<char, pdfium::FreeDeleter> font_data =
288 GetFileContents(font_path.c_str(), &file_length);
289 ASSERT_TRUE(font_data);
290
291 ScopedFPDFFont font(FPDFText_LoadFont(
292 document(), reinterpret_cast<const uint8_t*>(font_data.get()),
293 file_length, FPDF_FONT_TRUETYPE, /*cid=*/true));
294 FPDF_PAGEOBJECT text_object =
295 FPDFPageObj_CreateTextObj(document(), font.get(), 20.0f);
296 EXPECT_TRUE(text_object);
297
298 // Same as `text` in the EmbedNotoSansSCFont test case above.
299 const std::vector<uint32_t> charcodes = {9, 6, 7, 3, 5, 2, 1,
300 9, 6, 7, 4, 8, 2};
301 EXPECT_TRUE(
302 FPDFText_SetCharcodes(text_object, charcodes.data(), charcodes.size()));
303
304 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 50, 200);
305 FPDFPage_InsertObject(page.get(), text_object);
306 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
307
308#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Lei Zhang42d30c22022-01-12 19:24:43 +0000309#if BUILDFLAG(IS_APPLE)
Lei Zhang786544d2021-07-27 21:25:24 +0000310 const char kChecksum[] = "9a31fb87d1c6d2346bba22d1196041cd";
Lei Zhang42d30c22022-01-12 19:24:43 +0000311#else // BUILDFLAG(IS_APPLE)
Lei Zhang786544d2021-07-27 21:25:24 +0000312 const char kChecksum[] = "5bb65e15fc0a685934cd5006dec08a76";
Lei Zhang42d30c22022-01-12 19:24:43 +0000313#endif // BUILDFLAG(IS_APPLE)
Lei Zhang786544d2021-07-27 21:25:24 +0000314#else // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Lei Zhang786544d2021-07-27 21:25:24 +0000315 const char kChecksum[] = "9a31fb87d1c6d2346bba22d1196041cd";
Lei Zhang786544d2021-07-27 21:25:24 +0000316#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
317 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
318 CompareBitmap(page_bitmap.get(), 400, 400, kChecksum);
319
320 ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Hui Yingst8e88e382020-11-02 18:19:56 +0000321 VerifySavedDocument(400, 400, kChecksum);
322}
323
Lei Zhangab41f252018-12-23 03:10:50 +0000324TEST_F(FPDFEditEmbedderTest, EmptyCreation) {
Lei Zhangb8b4a042021-11-05 00:04:25 +0000325 CreateEmptyDocument();
weili9b777de2016-08-19 16:19:46 -0700326 FPDF_PAGE page = FPDFPage_New(document(), 0, 640.0, 480.0);
Tom Sepezd483eb42016-01-06 10:03:59 -0800327 EXPECT_NE(nullptr, page);
Nicolas Penad9d6c292017-06-06 16:12:10 -0400328 // The FPDFPage_GenerateContent call should do nothing.
Tom Sepezd483eb42016-01-06 10:03:59 -0800329 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Tom Sepez0aec19b2016-01-07 12:22:44 -0800330 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
etienneb7712c262016-04-26 08:13:45 -0700331
Nicolas Penad9d6c292017-06-06 16:12:10 -0400332 EXPECT_THAT(GetString(), testing::MatchesRegex(std::string(
333 kExpectedPDF, sizeof(kExpectedPDF))));
weili9b777de2016-08-19 16:19:46 -0700334 FPDF_ClosePage(page);
Tom Sepezd483eb42016-01-06 10:03:59 -0800335}
thestigdc7ec032016-11-21 15:32:52 -0800336
337// Regression test for https://crbug.com/667012
Lei Zhangab41f252018-12-23 03:10:50 +0000338TEST_F(FPDFEditEmbedderTest, RasterizePDF) {
thestigdc7ec032016-11-21 15:32:52 -0800339 const char kAllBlackMd5sum[] = "5708fc5c4a8bd0abde99c8e8f0390615";
340
Lei Zhangf0542892019-01-17 18:46:27 +0000341 // Get the bitmap for the original document.
Tom Sepeze08d2b12018-04-25 18:49:32 +0000342 ScopedFPDFBitmap orig_bitmap;
thestigdc7ec032016-11-21 15:32:52 -0800343 {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000344 ASSERT_TRUE(OpenDocument("black.pdf"));
thestigdc7ec032016-11-21 15:32:52 -0800345 FPDF_PAGE orig_page = LoadPage(0);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000346 ASSERT_TRUE(orig_page);
347 orig_bitmap = RenderLoadedPage(orig_page);
348 CompareBitmap(orig_bitmap.get(), 612, 792, kAllBlackMd5sum);
thestigdc7ec032016-11-21 15:32:52 -0800349 UnloadPage(orig_page);
350 }
351
352 // Create a new document from |orig_bitmap| and save it.
353 {
354 FPDF_DOCUMENT temp_doc = FPDF_CreateNewDocument();
355 FPDF_PAGE temp_page = FPDFPage_New(temp_doc, 0, 612, 792);
356
357 // Add the bitmap to an image object and add the image object to the output
358 // page.
Lei Zhangcbd89572017-03-15 17:35:47 -0700359 FPDF_PAGEOBJECT temp_img = FPDFPageObj_NewImageObj(temp_doc);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000360 EXPECT_TRUE(
361 FPDFImageObj_SetBitmap(&temp_page, 1, temp_img, orig_bitmap.get()));
Lei Zhangc8601bf2021-06-29 23:19:27 +0000362 static constexpr FS_MATRIX kLetterScaleMatrix{612, 0, 0, 792, 0, 0};
363 EXPECT_TRUE(FPDFPageObj_SetMatrix(temp_img, &kLetterScaleMatrix));
thestigdc7ec032016-11-21 15:32:52 -0800364 FPDFPage_InsertObject(temp_page, temp_img);
365 EXPECT_TRUE(FPDFPage_GenerateContent(temp_page));
366 EXPECT_TRUE(FPDF_SaveAsCopy(temp_doc, this, 0));
367 FPDF_ClosePage(temp_page);
368 FPDF_CloseDocument(temp_doc);
369 }
thestigdc7ec032016-11-21 15:32:52 -0800370
371 // Get the generated content. Make sure it is at least as big as the original
372 // PDF.
Lei Zhangd72fd582018-07-27 19:37:27 +0000373 EXPECT_GT(GetString().size(), 923u);
Dan Sinclair04e4dc82017-10-18 12:17:14 -0400374 VerifySavedDocument(612, 792, kAllBlackMd5sum);
thestigdc7ec032016-11-21 15:32:52 -0800375}
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500376
Hui Yingsta929df72021-02-26 23:56:18 +0000377TEST_F(FPDFEditEmbedderTest, AddPaths) {
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500378 // Start with a blank page
Nicolas Penad03ca422017-03-06 13:54:33 -0500379 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000380 ASSERT_TRUE(page);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500381
382 // We will first add a red rectangle
383 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000384 ASSERT_TRUE(red_rect);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500385 // Expect false when trying to set colors out of range
Lei Zhang3475b482019-05-13 18:30:57 +0000386 EXPECT_FALSE(FPDFPageObj_SetStrokeColor(red_rect, 100, 100, 100, 300));
387 EXPECT_FALSE(FPDFPageObj_SetFillColor(red_rect, 200, 256, 200, 0));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500388
389 // Fill rectangle with red and insert to the page
Lei Zhang3475b482019-05-13 18:30:57 +0000390 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500391 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
Miklos Vajna491112b2018-05-30 13:30:10 +0000392
393 int fillmode = FPDF_FILLMODE_NONE;
394 FPDF_BOOL stroke = true;
395 EXPECT_TRUE(FPDFPath_GetDrawMode(red_rect, &fillmode, &stroke));
396 EXPECT_EQ(FPDF_FILLMODE_ALTERNATE, fillmode);
397 EXPECT_FALSE(stroke);
398
Lei Zhangc8601bf2021-06-29 23:19:27 +0000399 static constexpr FS_MATRIX kMatrix = {1, 2, 3, 4, 5, 6};
400 EXPECT_TRUE(FPDFPageObj_SetMatrix(red_rect, &kMatrix));
Lei Zhang8da98232019-12-11 23:29:33 +0000401
402 FS_MATRIX matrix;
Lei Zhangc8601bf2021-06-29 23:19:27 +0000403 EXPECT_TRUE(FPDFPageObj_GetMatrix(red_rect, &matrix));
Lei Zhang8da98232019-12-11 23:29:33 +0000404 EXPECT_FLOAT_EQ(1.0f, matrix.a);
405 EXPECT_FLOAT_EQ(2.0f, matrix.b);
406 EXPECT_FLOAT_EQ(3.0f, matrix.c);
407 EXPECT_FLOAT_EQ(4.0f, matrix.d);
408 EXPECT_FLOAT_EQ(5.0f, matrix.e);
409 EXPECT_FLOAT_EQ(6.0f, matrix.f);
410
411 // Set back the identity matrix.
412 matrix = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
Lei Zhangc8601bf2021-06-29 23:19:27 +0000413 EXPECT_TRUE(FPDFPageObj_SetMatrix(red_rect, &matrix));
Miklos Vajna97f4d672018-06-04 14:47:17 +0000414
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500415 FPDFPage_InsertObject(page, red_rect);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000416 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000417 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +0000418 CompareBitmap(page_bitmap.get(), 612, 792, kRedRectangleChecksum);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000419 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500420
421 // Now add to that a green rectangle with some medium alpha
422 FPDF_PAGEOBJECT green_rect = FPDFPageObj_CreateNewRect(100, 100, 40, 40);
Lei Zhang3475b482019-05-13 18:30:57 +0000423 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_rect, 0, 255, 0, 128));
Miklos Vajnaed4705b2017-04-05 09:24:50 +0200424
Miklos Vajna1ef04c92017-05-08 18:14:19 +0200425 // Make sure the type of the rectangle is a path.
426 EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(green_rect));
427
Miklos Vajnaed4705b2017-04-05 09:24:50 +0200428 // Make sure we get back the same color we set previously.
429 unsigned int R;
430 unsigned int G;
431 unsigned int B;
432 unsigned int A;
Lei Zhang3475b482019-05-13 18:30:57 +0000433 EXPECT_TRUE(FPDFPageObj_GetFillColor(green_rect, &R, &G, &B, &A));
Lei Zhangd72fd582018-07-27 19:37:27 +0000434 EXPECT_EQ(0u, R);
435 EXPECT_EQ(255u, G);
436 EXPECT_EQ(0u, B);
437 EXPECT_EQ(128u, A);
Miklos Vajnaed4705b2017-04-05 09:24:50 +0200438
Lei Zhang9b4b8df2021-06-12 06:38:48 +0000439 // Make sure the path has 5 points (1 CFX_Path::Point::Type::kMove and 4
440 // CFX_Path::Point::Type::kLine).
Miklos Vajna0150a542017-09-21 21:46:56 +0200441 ASSERT_EQ(5, FPDFPath_CountSegments(green_rect));
Miklos Vajna36eed872017-09-20 22:52:43 +0200442 // Verify actual coordinates.
443 FPDF_PATHSEGMENT segment = FPDFPath_GetPathSegment(green_rect, 0);
444 float x;
445 float y;
446 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
447 EXPECT_EQ(100, x);
448 EXPECT_EQ(100, y);
449 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
450 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
451 segment = FPDFPath_GetPathSegment(green_rect, 1);
452 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
453 EXPECT_EQ(100, x);
454 EXPECT_EQ(140, y);
455 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
456 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
457 segment = FPDFPath_GetPathSegment(green_rect, 2);
458 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
459 EXPECT_EQ(140, x);
460 EXPECT_EQ(140, y);
461 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
462 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
463 segment = FPDFPath_GetPathSegment(green_rect, 3);
464 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
465 EXPECT_EQ(140, x);
466 EXPECT_EQ(100, y);
467 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
468 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
469 segment = FPDFPath_GetPathSegment(green_rect, 4);
470 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
471 EXPECT_EQ(100, x);
472 EXPECT_EQ(100, y);
473 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
474 EXPECT_TRUE(FPDFPathSegment_GetClose(segment));
Miklos Vajna12abfd02017-09-15 07:49:03 +0200475
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500476 EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect, FPDF_FILLMODE_WINDING, 0));
477 FPDFPage_InsertObject(page, green_rect);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000478 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000479 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000480 CompareBitmap(page_bitmap.get(), 612, 792,
481 "7b0b87604594e773add528fae567a558");
482 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500483
484 // Add a black triangle.
485 FPDF_PAGEOBJECT black_path = FPDFPageObj_CreateNewPath(400, 100);
Lei Zhang3475b482019-05-13 18:30:57 +0000486 EXPECT_TRUE(FPDFPageObj_SetFillColor(black_path, 0, 0, 0, 200));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500487 EXPECT_TRUE(FPDFPath_SetDrawMode(black_path, FPDF_FILLMODE_ALTERNATE, 0));
488 EXPECT_TRUE(FPDFPath_LineTo(black_path, 400, 200));
489 EXPECT_TRUE(FPDFPath_LineTo(black_path, 300, 100));
490 EXPECT_TRUE(FPDFPath_Close(black_path));
Miklos Vajna12abfd02017-09-15 07:49:03 +0200491
Lei Zhang9b4b8df2021-06-12 06:38:48 +0000492 // Make sure the path has 3 points (1 CFX_Path::Point::Type::kMove and 2
493 // CFX_Path::Point::Type::kLine).
Miklos Vajna0150a542017-09-21 21:46:56 +0200494 ASSERT_EQ(3, FPDFPath_CountSegments(black_path));
Miklos Vajna36eed872017-09-20 22:52:43 +0200495 // Verify actual coordinates.
496 segment = FPDFPath_GetPathSegment(black_path, 0);
497 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
498 EXPECT_EQ(400, x);
499 EXPECT_EQ(100, y);
500 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
501 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
502 segment = FPDFPath_GetPathSegment(black_path, 1);
503 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
504 EXPECT_EQ(400, x);
505 EXPECT_EQ(200, y);
506 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
507 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
508 segment = FPDFPath_GetPathSegment(black_path, 2);
509 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
510 EXPECT_EQ(300, x);
511 EXPECT_EQ(100, y);
512 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
513 EXPECT_TRUE(FPDFPathSegment_GetClose(segment));
514 // Make sure out of bounds index access fails properly.
515 EXPECT_EQ(nullptr, FPDFPath_GetPathSegment(black_path, 3));
Miklos Vajna12abfd02017-09-15 07:49:03 +0200516
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500517 FPDFPage_InsertObject(page, black_path);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000518 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000519 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000520 CompareBitmap(page_bitmap.get(), 612, 792,
521 "eadc8020a14dfcf091da2688733d8806");
522 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500523
524 // Now add a more complex blue path.
525 FPDF_PAGEOBJECT blue_path = FPDFPageObj_CreateNewPath(200, 200);
Lei Zhang3475b482019-05-13 18:30:57 +0000526 EXPECT_TRUE(FPDFPageObj_SetFillColor(blue_path, 0, 0, 255, 255));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500527 EXPECT_TRUE(FPDFPath_SetDrawMode(blue_path, FPDF_FILLMODE_WINDING, 0));
528 EXPECT_TRUE(FPDFPath_LineTo(blue_path, 230, 230));
529 EXPECT_TRUE(FPDFPath_BezierTo(blue_path, 250, 250, 280, 280, 300, 300));
530 EXPECT_TRUE(FPDFPath_LineTo(blue_path, 325, 325));
531 EXPECT_TRUE(FPDFPath_LineTo(blue_path, 350, 325));
532 EXPECT_TRUE(FPDFPath_BezierTo(blue_path, 375, 330, 390, 360, 400, 400));
533 EXPECT_TRUE(FPDFPath_Close(blue_path));
534 FPDFPage_InsertObject(page, blue_path);
Hui Yingsta929df72021-02-26 23:56:18 +0000535#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
536 static constexpr char kLastChecksum[] = "ed14c60702b1489c597c7d46ece7f86d";
537#else
538 static constexpr char kLastChecksum[] = "9823e1a21bd9b72b6a442ba4f12af946";
539#endif
Lei Zhang107fa7b2018-02-09 21:48:15 +0000540 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000541 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingsta929df72021-02-26 23:56:18 +0000542 CompareBitmap(page_bitmap.get(), 612, 792, kLastChecksum);
Lei Zhang107fa7b2018-02-09 21:48:15 +0000543 }
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500544
545 // Now save the result, closing the page and document
Nicolas Pena207b7272017-05-26 17:37:06 -0400546 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Nicolas Penad03ca422017-03-06 13:54:33 -0500547 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500548 FPDF_ClosePage(page);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500549
550 // Render the saved result
Hui Yingsta929df72021-02-26 23:56:18 +0000551 VerifySavedDocument(612, 792, kLastChecksum);
Nicolas Pena0fc185e2017-02-08 12:13:20 -0500552}
553
Miklos Vajna45501f32019-07-30 07:41:02 +0000554TEST_F(FPDFEditEmbedderTest, ClipPath) {
555 // Load document with a clipped rectangle.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000556 ASSERT_TRUE(OpenDocument("clip_path.pdf"));
Miklos Vajna45501f32019-07-30 07:41:02 +0000557 FPDF_PAGE page = LoadPage(0);
558 ASSERT_TRUE(page);
559
560 ASSERT_EQ(1, FPDFPage_CountObjects(page));
561
562 FPDF_PAGEOBJECT triangle = FPDFPage_GetObject(page, 0);
563 ASSERT_TRUE(triangle);
564
565 // Test that we got the expected triangle.
566 ASSERT_EQ(4, FPDFPath_CountSegments(triangle));
567
568 FPDF_PATHSEGMENT segment = FPDFPath_GetPathSegment(triangle, 0);
569 float x;
570 float y;
571 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
572 EXPECT_EQ(10, x);
573 EXPECT_EQ(10, y);
574 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
575 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
576
577 segment = FPDFPath_GetPathSegment(triangle, 1);
578 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
579 EXPECT_EQ(25, x);
580 EXPECT_EQ(40, y);
581 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
582 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
583
584 segment = FPDFPath_GetPathSegment(triangle, 2);
585 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
586 EXPECT_EQ(40, x);
587 EXPECT_EQ(10, y);
588 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
589 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
590
591 segment = FPDFPath_GetPathSegment(triangle, 3);
592 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
593 EXPECT_TRUE(FPDFPathSegment_GetClose(segment));
594
595 // Test FPDFPageObj_GetClipPath().
596 ASSERT_EQ(nullptr, FPDFPageObj_GetClipPath(nullptr));
597
598 FPDF_CLIPPATH clip_path = FPDFPageObj_GetClipPath(triangle);
599 ASSERT_TRUE(clip_path);
600
601 // Test FPDFClipPath_CountPaths().
602 ASSERT_EQ(-1, FPDFClipPath_CountPaths(nullptr));
603 ASSERT_EQ(1, FPDFClipPath_CountPaths(clip_path));
604
605 // Test FPDFClipPath_CountPathSegments().
606 ASSERT_EQ(-1, FPDFClipPath_CountPathSegments(nullptr, 0));
607 ASSERT_EQ(-1, FPDFClipPath_CountPathSegments(clip_path, -1));
608 ASSERT_EQ(-1, FPDFClipPath_CountPathSegments(clip_path, 1));
609 ASSERT_EQ(4, FPDFClipPath_CountPathSegments(clip_path, 0));
610
611 // FPDFClipPath_GetPathSegment() negative testing.
612 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(nullptr, 0, 0));
613 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, -1, 0));
614 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, 1, 0));
615 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, 0, -1));
616 ASSERT_EQ(nullptr, FPDFClipPath_GetPathSegment(clip_path, 0, 4));
617
618 // FPDFClipPath_GetPathSegment() positive testing.
619 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 0);
620 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
621 EXPECT_EQ(10, x);
622 EXPECT_EQ(15, y);
623 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
624 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
625
626 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 1);
627 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
628 EXPECT_EQ(40, x);
629 EXPECT_EQ(15, y);
630 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
631 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
632
633 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 2);
634 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
635 EXPECT_EQ(40, x);
636 EXPECT_EQ(35, y);
637 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
638 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
639
640 segment = FPDFClipPath_GetPathSegment(clip_path, 0, 3);
641 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
642 EXPECT_EQ(10, x);
643 EXPECT_EQ(35, y);
644 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
645 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
646
647 UnloadPage(page);
648}
649
Lei Zhang571f9322019-09-25 12:40:25 +0000650TEST_F(FPDFEditEmbedderTest, BUG_1399) {
651 // Load document with a clipped rectangle.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000652 ASSERT_TRUE(OpenDocument("bug_1399.pdf"));
Lei Zhang571f9322019-09-25 12:40:25 +0000653 FPDF_PAGE page = LoadPage(0);
654 ASSERT_TRUE(page);
655
656 ASSERT_EQ(7, FPDFPage_CountObjects(page));
657
658 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
659 ASSERT_TRUE(obj);
660
661 ASSERT_EQ(2, FPDFPath_CountSegments(obj));
662
663 FPDF_PATHSEGMENT segment = FPDFPath_GetPathSegment(obj, 0);
664 float x;
665 float y;
666 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
667 EXPECT_FLOAT_EQ(107.718f, x);
668 EXPECT_FLOAT_EQ(719.922f, y);
669 EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
670 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
671
672 segment = FPDFPath_GetPathSegment(obj, 1);
673 EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
674 EXPECT_FLOAT_EQ(394.718f, x);
675 EXPECT_FLOAT_EQ(719.922f, y);
676 EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
677 EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
678
679 FPDF_CLIPPATH clip_path = FPDFPageObj_GetClipPath(obj);
680 ASSERT_TRUE(clip_path);
681
682 EXPECT_EQ(-1, FPDFClipPath_CountPaths(clip_path));
683 EXPECT_EQ(-1, FPDFClipPath_CountPathSegments(clip_path, 0));
684 EXPECT_FALSE(FPDFClipPath_GetPathSegment(clip_path, 0, 0));
685
686 UnloadPage(page);
687}
688
Lei Zhangfcf7e7f2021-07-02 18:46:54 +0000689TEST_F(FPDFEditEmbedderTest, BUG_1549) {
690 static const char kOriginalChecksum[] = "126366fb95e6caf8ea196780075b22b2";
691 static const char kRemovedChecksum[] = "6ec2f27531927882624b37bc7d8e12f4";
692
693 ASSERT_TRUE(OpenDocument("bug_1549.pdf"));
694 FPDF_PAGE page = LoadPage(0);
695
696 {
697 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
698 CompareBitmap(bitmap.get(), 100, 150, kOriginalChecksum);
699
700 ScopedFPDFPageObject obj(FPDFPage_GetObject(page, 0));
701 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj.get()));
702 ASSERT_TRUE(FPDFPage_RemoveObject(page, obj.get()));
703 }
704
705 ASSERT_TRUE(FPDFPage_GenerateContent(page));
706
707 {
708 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
709 CompareBitmap(bitmap.get(), 100, 150, kRemovedChecksum);
710 }
711
712 ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
713 UnloadPage(page);
714
715 // TODO(crbug.com/pdfium/1549): Should be `kRemovedChecksum`.
716 VerifySavedDocument(100, 150, "4f9889cd5993db20f1ab37d677ac8d26");
717}
718
Hui Yingstcb4203d2020-06-09 01:48:47 +0000719TEST_F(FPDFEditEmbedderTest, SetText) {
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000720 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000721 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000722 FPDF_PAGE page = LoadPage(0);
723 ASSERT_TRUE(page);
724
725 // Get the "Hello, world!" text object and change it.
726 ASSERT_EQ(2, FPDFPage_CountObjects(page));
727 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
728 ASSERT_TRUE(page_object);
Lei Zhangf0f67682019-04-08 17:03:21 +0000729 ScopedFPDFWideString text1 = GetFPDFWideString(L"Changed for SetText test");
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000730 EXPECT_TRUE(FPDFText_SetText(page_object, text1.get()));
731
732 // Verify the "Hello, world!" text is gone and "Changed for SetText test" is
733 // now displayed.
734 ASSERT_EQ(2, FPDFPage_CountObjects(page));
Hui Yingstcb4203d2020-06-09 01:48:47 +0000735
736#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +0000737 const char kChangedChecksum[] = "49c8602cb60508009a34d0caaac63bb4";
Lei Zhang42d30c22022-01-12 19:24:43 +0000738#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +0000739 const char kChangedChecksum[] = "b720e83476fd6819d47c533f1f43c728";
Hui Yingstcb4203d2020-06-09 01:48:47 +0000740#else
Tom Andersond4fe5f72021-12-03 20:52:52 +0000741 const char kChangedChecksum[] = "9a85b9354a69c61772ed24151c140f46";
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000742#endif
743 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000744 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstcb4203d2020-06-09 01:48:47 +0000745 CompareBitmap(page_bitmap.get(), 200, 200, kChangedChecksum);
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000746 }
747
748 // Now save the result.
749 EXPECT_TRUE(FPDFPage_GenerateContent(page));
750 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
751
752 UnloadPage(page);
753
754 // Re-open the file and check the changes were kept in the saved .pdf.
Lei Zhang0b494052019-01-31 21:41:15 +0000755 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000756 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +0000757 ASSERT_TRUE(saved_page);
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000758 EXPECT_EQ(2, FPDFPage_CountObjects(saved_page));
759 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000760 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstcb4203d2020-06-09 01:48:47 +0000761 CompareBitmap(page_bitmap.get(), 200, 200, kChangedChecksum);
Henrique Nakashima5ebfd642018-06-07 15:18:55 +0000762 }
763
764 CloseSavedPage(saved_page);
765 CloseSavedDocument();
766}
767
Lei Zhang786544d2021-07-27 21:25:24 +0000768TEST_F(FPDFEditEmbedderTest, SetCharcodesBadParams) {
769 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
770 FPDF_PAGE page = LoadPage(0);
771 ASSERT_TRUE(page);
772
773 ASSERT_EQ(2, FPDFPage_CountObjects(page));
774 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
775 ASSERT_TRUE(page_object);
776
777 const uint32_t kDummyValue = 42;
778 EXPECT_FALSE(FPDFText_SetCharcodes(nullptr, nullptr, 0));
779 EXPECT_FALSE(FPDFText_SetCharcodes(nullptr, nullptr, 1));
780 EXPECT_FALSE(FPDFText_SetCharcodes(nullptr, &kDummyValue, 0));
781 EXPECT_FALSE(FPDFText_SetCharcodes(nullptr, &kDummyValue, 1));
782 EXPECT_FALSE(FPDFText_SetCharcodes(page_object, nullptr, 1));
783
784 UnloadPage(page);
785}
786
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000787TEST_F(FPDFEditEmbedderTest, SetTextKeepClippingPath) {
Daniel Hosseinianda651442020-07-17 23:30:22 +0000788 // Load document with some text, with parts clipped.
789 ASSERT_TRUE(OpenDocument("bug_1558.pdf"));
790 FPDF_PAGE page = LoadPage(0);
791 ASSERT_TRUE(page);
792
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000793#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Daniel Hosseinianda651442020-07-17 23:30:22 +0000794 static constexpr char kOriginalChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +0000795 "92ff84385a0f986eacfa4bbecf8d7a7a";
Lei Zhang42d30c22022-01-12 19:24:43 +0000796#elif BUILDFLAG(IS_APPLE)
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000797 static constexpr char kOriginalChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +0000798 "ae7a25c85e0e2dd0c5cb9dd5cd37f6df";
Daniel Hosseinianda651442020-07-17 23:30:22 +0000799#else
Hui Yingst5ce6a3f2020-11-11 02:29:09 +0000800 static constexpr char kOriginalChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +0000801 "7af7fe5b281298261eb66ac2d22f5054";
Daniel Hosseinianda651442020-07-17 23:30:22 +0000802#endif
803 {
804 // When opened before any editing and saving, the clipping path is rendered.
805 ScopedFPDFBitmap original_bitmap = RenderPage(page);
806 CompareBitmap(original_bitmap.get(), 200, 200, kOriginalChecksum);
807 }
808
809 // "Change" the text in the objects to their current values to force them to
810 // regenerate when saving.
811 {
812 ScopedFPDFTextPage text_page(FPDFText_LoadPage(page));
813 ASSERT_TRUE(text_page);
814 const int obj_count = FPDFPage_CountObjects(page);
815 ASSERT_EQ(2, obj_count);
816 for (int i = 0; i < obj_count; ++i) {
817 FPDF_PAGEOBJECT text_obj = FPDFPage_GetObject(page, i);
818 ASSERT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(text_obj));
819 unsigned long size =
820 FPDFTextObj_GetText(text_obj, text_page.get(),
821 /*buffer=*/nullptr, /*length=*/0);
822 ASSERT_GT(size, 0u);
823 std::vector<FPDF_WCHAR> buffer = GetFPDFWideStringBuffer(size);
824 ASSERT_EQ(size, FPDFTextObj_GetText(text_obj, text_page.get(),
825 buffer.data(), size));
826 EXPECT_TRUE(FPDFText_SetText(text_obj, buffer.data()));
827 }
828 }
829
830 {
831 // After editing but before saving, the clipping path is retained.
832 ScopedFPDFBitmap edited_bitmap = RenderPage(page);
833 CompareBitmap(edited_bitmap.get(), 200, 200, kOriginalChecksum);
834 }
835
836 // Save the file.
837 EXPECT_TRUE(FPDFPage_GenerateContent(page));
838 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
839 UnloadPage(page);
840
841 // Open the saved copy and render it.
842 ASSERT_TRUE(OpenSavedDocument());
843 FPDF_PAGE saved_page = LoadSavedPage(0);
844 ASSERT_TRUE(saved_page);
845
846 {
Daniel Hosseinianda651442020-07-17 23:30:22 +0000847 ScopedFPDFBitmap saved_bitmap = RenderSavedPage(saved_page);
Daniel Hosseinian75efd912020-07-21 08:07:28 +0000848 CompareBitmap(saved_bitmap.get(), 200, 200, kOriginalChecksum);
Daniel Hosseinianda651442020-07-17 23:30:22 +0000849 }
850
851 CloseSavedPage(saved_page);
852 CloseSavedDocument();
853}
854
Daniel Hosseinian7b819bf2021-01-27 19:40:34 +0000855TEST_F(FPDFEditEmbedderTest, BUG_1574) {
856 // Load document with some text within a clipping path.
857 ASSERT_TRUE(OpenDocument("bug_1574.pdf"));
858 FPDF_PAGE page = LoadPage(0);
859 ASSERT_TRUE(page);
860
861#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
862 static constexpr char kOriginalChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +0000863 "1e022a0360f053ecb41cc431a36834a6";
Lei Zhang42d30c22022-01-12 19:24:43 +0000864#elif BUILDFLAG(IS_APPLE)
Daniel Hosseinian7b819bf2021-01-27 19:40:34 +0000865 static constexpr char kOriginalChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +0000866 "1226bc2b8072622eb28f52321876e814";
Daniel Hosseinian7b819bf2021-01-27 19:40:34 +0000867#else
868 static constexpr char kOriginalChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +0000869 "c5241eef60b9eac68ed1f2a5fd002703";
Daniel Hosseinian7b819bf2021-01-27 19:40:34 +0000870#endif
Daniel Hosseinian7b819bf2021-01-27 19:40:34 +0000871 {
872 // When opened before any editing and saving, the text object is rendered.
873 ScopedFPDFBitmap original_bitmap = RenderPage(page);
874 CompareBitmap(original_bitmap.get(), 200, 300, kOriginalChecksum);
875 }
876
877 // "Change" the text in the objects to their current values to force them to
878 // regenerate when saving.
879 {
880 ScopedFPDFTextPage text_page(FPDFText_LoadPage(page));
881 ASSERT_TRUE(text_page);
882
883 ASSERT_EQ(2, FPDFPage_CountObjects(page));
884 FPDF_PAGEOBJECT text_obj = FPDFPage_GetObject(page, 1);
885 ASSERT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(text_obj));
886
887 unsigned long size = FPDFTextObj_GetText(text_obj, text_page.get(),
888 /*buffer=*/nullptr, /*length=*/0);
889 ASSERT_GT(size, 0u);
890 std::vector<FPDF_WCHAR> buffer = GetFPDFWideStringBuffer(size);
891 ASSERT_EQ(size, FPDFTextObj_GetText(text_obj, text_page.get(),
892 buffer.data(), size));
893 EXPECT_TRUE(FPDFText_SetText(text_obj, buffer.data()));
894 }
895
896 // Save the file.
897 EXPECT_TRUE(FPDFPage_GenerateContent(page));
898 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
899 UnloadPage(page);
900
901 // Open the saved copy and render it.
902 ASSERT_TRUE(OpenSavedDocument());
903 FPDF_PAGE saved_page = LoadSavedPage(0);
904 ASSERT_TRUE(saved_page);
905
Daniel Hosseinian7b819bf2021-01-27 19:40:34 +0000906 {
907 ScopedFPDFBitmap saved_bitmap = RenderSavedPage(saved_page);
Daniel Hosseinian91eeeb92021-01-27 19:53:24 +0000908 CompareBitmap(saved_bitmap.get(), 200, 300, kOriginalChecksum);
Daniel Hosseinian7b819bf2021-01-27 19:40:34 +0000909 }
910
911 CloseSavedPage(saved_page);
912 CloseSavedDocument();
913}
914
Hui Yingst08c40712020-04-29 01:37:35 +0000915TEST_F(FPDFEditEmbedderTest, RemovePageObject) {
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000916 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +0000917 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000918 FPDF_PAGE page = LoadPage(0);
919 ASSERT_TRUE(page);
920
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000921 // Show what the original file looks like.
922 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000923 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +0000924 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000925 }
926
927 // Get the "Hello, world!" text object and remove it.
928 ASSERT_EQ(2, FPDFPage_CountObjects(page));
929 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
930 ASSERT_TRUE(page_object);
931 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
932
Henrique Nakashimac90adc52018-03-27 16:26:44 +0000933 // Verify the "Hello, world!" text is gone.
934 {
Lei Zhang30ff2532019-01-31 21:37:55 +0000935 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +0000936 CompareBitmap(page_bitmap.get(), 200, 200, kFirstRemovedChecksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +0000937 }
938 ASSERT_EQ(1, FPDFPage_CountObjects(page));
939
940 UnloadPage(page);
941 FPDFPageObj_Destroy(page_object);
942}
943
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000944void CheckMarkCounts(FPDF_PAGE page,
945 int start_from,
946 int expected_object_count,
947 size_t expected_prime_count,
948 size_t expected_square_count,
949 size_t expected_greater_than_ten_count,
950 size_t expected_bounds_count) {
951 int object_count = FPDFPage_CountObjects(page);
952 ASSERT_EQ(expected_object_count, object_count);
953
954 size_t prime_count = 0;
955 size_t square_count = 0;
956 size_t greater_than_ten_count = 0;
957 size_t bounds_count = 0;
958 for (int i = 0; i < object_count; ++i) {
959 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
960
961 int mark_count = FPDFPageObj_CountMarks(page_object);
962 for (int j = 0; j < mark_count; ++j) {
963 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
964
965 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +0000966 unsigned long name_len = 999u;
967 ASSERT_TRUE(
968 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
969 EXPECT_GT(name_len, 0u);
970 EXPECT_NE(999u, name_len);
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000971 std::wstring name =
972 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
973 if (name == L"Prime") {
974 prime_count++;
975 } else if (name == L"Square") {
976 square_count++;
977 int expected_square = start_from + i;
978 EXPECT_EQ(1, FPDFPageObjMark_CountParams(mark));
979
Henrique Nakashimac3099d12018-09-18 18:08:15 +0000980 unsigned long get_param_key_return = 999u;
981 ASSERT_TRUE(FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer),
982 &get_param_key_return));
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000983 EXPECT_EQ((6u + 1u) * 2u, get_param_key_return);
984 std::wstring key =
985 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
986 EXPECT_EQ(L"Factor", key);
987
988 EXPECT_EQ(FPDF_OBJECT_NUMBER,
Henrique Nakashima94230e52018-07-11 22:02:02 +0000989 FPDFPageObjMark_GetParamValueType(mark, "Factor"));
Henrique Nakashima140dead2018-07-11 21:40:03 +0000990 int square_root;
Henrique Nakashima94230e52018-07-11 22:02:02 +0000991 EXPECT_TRUE(
992 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &square_root));
Henrique Nakashimacbed9492018-07-10 21:54:26 +0000993 EXPECT_EQ(expected_square, square_root * square_root);
994 } else if (name == L"GreaterThanTen") {
995 greater_than_ten_count++;
996 } else if (name == L"Bounds") {
997 bounds_count++;
998 EXPECT_EQ(1, FPDFPageObjMark_CountParams(mark));
999
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001000 unsigned long get_param_key_return = 999u;
1001 ASSERT_TRUE(FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer),
1002 &get_param_key_return));
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001003 EXPECT_EQ((8u + 1u) * 2u, get_param_key_return);
1004 std::wstring key =
1005 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1006 EXPECT_EQ(L"Position", key);
1007
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001008 EXPECT_EQ(FPDF_OBJECT_STRING,
Henrique Nakashima94230e52018-07-11 22:02:02 +00001009 FPDFPageObjMark_GetParamValueType(mark, "Position"));
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001010 unsigned long length;
Henrique Nakashimaa3406772018-07-13 19:10:53 +00001011 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
1012 mark, "Position", buffer, sizeof(buffer), &length));
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001013 ASSERT_GT(length, 0u);
Henrique Nakashima140dead2018-07-11 21:40:03 +00001014 std::wstring value =
1015 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00001016
Henrique Nakashimaa3406772018-07-13 19:10:53 +00001017 // "Position" can be "First", "Last", or "End".
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00001018 if (i == 0) {
1019 EXPECT_EQ((5u + 1u) * 2u, length);
1020 EXPECT_EQ(L"First", value);
1021 } else if (i == object_count - 1) {
Henrique Nakashimaa3406772018-07-13 19:10:53 +00001022 if (length == (4u + 1u) * 2u) {
1023 EXPECT_EQ(L"Last", value);
1024 } else if (length == (3u + 1u) * 2u) {
1025 EXPECT_EQ(L"End", value);
1026 } else {
1027 FAIL();
1028 }
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00001029 } else {
1030 FAIL();
1031 }
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001032 } else {
1033 FAIL();
1034 }
1035 }
1036 }
1037
1038 // Expect certain number of tagged objects. The test file contains strings
1039 // from 1 to 19.
1040 EXPECT_EQ(expected_prime_count, prime_count);
1041 EXPECT_EQ(expected_square_count, square_count);
1042 EXPECT_EQ(expected_greater_than_ten_count, greater_than_ten_count);
1043 EXPECT_EQ(expected_bounds_count, bounds_count);
1044}
1045
Lei Zhangab41f252018-12-23 03:10:50 +00001046TEST_F(FPDFEditEmbedderTest, ReadMarkedObjectsIndirectDict) {
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001047 // Load document with some text marked with an indirect property.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001048 ASSERT_TRUE(OpenDocument("text_in_page_marked_indirect.pdf"));
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001049 FPDF_PAGE page = LoadPage(0);
1050 ASSERT_TRUE(page);
1051
1052 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
1053
1054 UnloadPage(page);
1055}
1056
Hui Yingstf26b5f82020-11-17 05:26:03 +00001057TEST_F(FPDFEditEmbedderTest, RemoveMarkedObjectsPrime) {
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001058 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001059 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001060 FPDF_PAGE page = LoadPage(0);
1061 ASSERT_TRUE(page);
1062
1063 // Show what the original file looks like.
1064 {
Hui Yingstf26b5f82020-11-17 05:26:03 +00001065#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1066 static constexpr char kOriginalChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +00001067 "8a8bed7820764522955f422e27f4292f";
Lei Zhang42d30c22022-01-12 19:24:43 +00001068#elif BUILDFLAG(IS_APPLE)
Hui Yingstf26b5f82020-11-17 05:26:03 +00001069 static constexpr char kOriginalChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +00001070 "966579fb98206858ce2f0a1f94a74d05";
Hui Yingstf26b5f82020-11-17 05:26:03 +00001071#else
1072 static constexpr char kOriginalChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +00001073 "3d5a3de53d5866044c2b6bf339742c97";
1074#endif
Lei Zhang30ff2532019-01-31 21:37:55 +00001075 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstf26b5f82020-11-17 05:26:03 +00001076 CompareBitmap(page_bitmap.get(), 200, 200, kOriginalChecksum);
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001077 }
1078
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001079 constexpr int expected_object_count = 19;
1080 CheckMarkCounts(page, 1, expected_object_count, 8, 4, 9, 1);
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001081
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001082 // Get all objects marked with "Prime"
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001083 std::vector<FPDF_PAGEOBJECT> primes;
Henrique Nakashimacbed9492018-07-10 21:54:26 +00001084 for (int i = 0; i < expected_object_count; ++i) {
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001085 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1086
1087 int mark_count = FPDFPageObj_CountMarks(page_object);
1088 for (int j = 0; j < mark_count; ++j) {
1089 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
1090
1091 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001092 unsigned long name_len = 999u;
1093 ASSERT_TRUE(
1094 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
1095 EXPECT_GT(name_len, 0u);
1096 EXPECT_NE(999u, name_len);
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001097 std::wstring name =
1098 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1099 if (name == L"Prime") {
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001100 primes.push_back(page_object);
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001101 }
1102 }
1103 }
1104
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001105 // Remove all objects marked with "Prime".
1106 for (FPDF_PAGEOBJECT page_object : primes) {
1107 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1108 FPDFPageObj_Destroy(page_object);
1109 }
1110
1111 EXPECT_EQ(11, FPDFPage_CountObjects(page));
Hui Yingstf26b5f82020-11-17 05:26:03 +00001112#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1113 static constexpr char kNonPrimesChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +00001114 "1573b85dd9a2c59401c1c30abbee3b25";
Hui Yingstf26b5f82020-11-17 05:26:03 +00001115 static constexpr char kNonPrimesAfterSaveChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +00001116 "1573b85dd9a2c59401c1c30abbee3b25";
Lei Zhang42d30c22022-01-12 19:24:43 +00001117#elif BUILDFLAG(IS_APPLE)
Hui Yingstf26b5f82020-11-17 05:26:03 +00001118 static constexpr char kNonPrimesChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +00001119 "6e19a4dd674b522cd39cf41956559bd6";
Hui Yingstf26b5f82020-11-17 05:26:03 +00001120 static constexpr char kNonPrimesAfterSaveChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +00001121 "3cb35c681f8fb5a43a49146ac7caa818";
Hui Yingstf26b5f82020-11-17 05:26:03 +00001122#else
1123 static constexpr char kNonPrimesChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +00001124 "bc8623c052f12376c3d8dd09a6cd27df";
Hui Yingstf26b5f82020-11-17 05:26:03 +00001125 static constexpr char kNonPrimesAfterSaveChecksum[] =
Tom Andersond4fe5f72021-12-03 20:52:52 +00001126 "bc8623c052f12376c3d8dd09a6cd27df";
1127#endif
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001128 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001129 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstf26b5f82020-11-17 05:26:03 +00001130 CompareBitmap(page_bitmap.get(), 200, 200, kNonPrimesChecksum);
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001131 }
1132
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001133 // Save the file.
1134 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1135 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001136 UnloadPage(page);
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001137
1138 // Re-open the file and check the prime marks are not there anymore.
Lei Zhang0b494052019-01-31 21:41:15 +00001139 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001140 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001141 ASSERT_TRUE(saved_page);
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001142 EXPECT_EQ(11, FPDFPage_CountObjects(saved_page));
1143
1144 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001145 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstf26b5f82020-11-17 05:26:03 +00001146 CompareBitmap(page_bitmap.get(), 200, 200, kNonPrimesAfterSaveChecksum);
Henrique Nakashimaa5078b72018-09-10 17:09:42 +00001147 }
1148
1149 CloseSavedPage(saved_page);
1150 CloseSavedDocument();
Henrique Nakashimac90adc52018-03-27 16:26:44 +00001151}
1152
Lei Zhangab41f252018-12-23 03:10:50 +00001153TEST_F(FPDFEditEmbedderTest, RemoveMarks) {
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001154 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001155 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001156 FPDF_PAGE page = LoadPage(0);
1157 ASSERT_TRUE(page);
1158
1159 constexpr int kExpectedObjectCount = 19;
1160 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
1161
1162 // Remove all "Prime" content marks.
1163 for (int i = 0; i < kExpectedObjectCount; ++i) {
1164 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1165
1166 int mark_count = FPDFPageObj_CountMarks(page_object);
1167 for (int j = mark_count - 1; j >= 0; --j) {
1168 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
1169
1170 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001171 unsigned long name_len = 999u;
1172 ASSERT_TRUE(
1173 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
1174 EXPECT_GT(name_len, 0u);
1175 EXPECT_NE(999u, name_len);
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001176 std::wstring name =
1177 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1178 if (name == L"Prime") {
1179 // Remove mark.
1180 EXPECT_TRUE(FPDFPageObj_RemoveMark(page_object, mark));
1181
1182 // Verify there is now one fewer mark in the page object.
1183 EXPECT_EQ(mark_count - 1, FPDFPageObj_CountMarks(page_object));
1184 }
1185 }
1186 }
1187
1188 // Verify there are 0 "Prime" content marks now.
1189 CheckMarkCounts(page, 1, kExpectedObjectCount, 0, 4, 9, 1);
1190
1191 // Save the file.
1192 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1193 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1194 UnloadPage(page);
1195
1196 // Re-open the file and check the prime marks are not there anymore.
Lei Zhang0b494052019-01-31 21:41:15 +00001197 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001198 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001199 ASSERT_TRUE(saved_page);
Henrique Nakashimafed4adb2018-07-13 19:47:22 +00001200
1201 CheckMarkCounts(saved_page, 1, kExpectedObjectCount, 0, 4, 9, 1);
1202
1203 CloseSavedPage(saved_page);
1204 CloseSavedDocument();
1205}
1206
Lei Zhangab41f252018-12-23 03:10:50 +00001207TEST_F(FPDFEditEmbedderTest, RemoveMarkParam) {
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001208 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001209 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001210 FPDF_PAGE page = LoadPage(0);
1211 ASSERT_TRUE(page);
1212
1213 constexpr int kExpectedObjectCount = 19;
1214 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
1215
1216 // Remove all "Square" content marks parameters.
1217 for (int i = 0; i < kExpectedObjectCount; ++i) {
1218 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1219
1220 int mark_count = FPDFPageObj_CountMarks(page_object);
1221 for (int j = 0; j < mark_count; ++j) {
1222 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
1223
1224 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001225 unsigned long name_len = 999u;
1226 ASSERT_TRUE(
1227 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
1228 EXPECT_GT(name_len, 0u);
1229 EXPECT_NE(999u, name_len);
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001230 std::wstring name =
1231 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1232 if (name == L"Square") {
1233 // Show the mark has a "Factor" parameter.
1234 int out_value;
1235 EXPECT_TRUE(
1236 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
1237
1238 // Remove parameter.
1239 EXPECT_TRUE(FPDFPageObjMark_RemoveParam(page_object, mark, "Factor"));
1240
1241 // Verify the "Factor" parameter is gone.
1242 EXPECT_FALSE(
1243 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
1244 }
1245 }
1246 }
1247
1248 // Save the file.
1249 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1250 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1251 UnloadPage(page);
1252
1253 // Re-open the file and check the "Factor" parameters are still gone.
Lei Zhang0b494052019-01-31 21:41:15 +00001254 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001255 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001256 ASSERT_TRUE(saved_page);
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001257
1258 size_t square_count = 0;
1259 for (int i = 0; i < kExpectedObjectCount; ++i) {
1260 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(saved_page, i);
1261
1262 int mark_count = FPDFPageObj_CountMarks(page_object);
1263 for (int j = 0; j < mark_count; ++j) {
1264 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
1265
1266 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00001267 unsigned long name_len = 999u;
1268 ASSERT_TRUE(
1269 FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
1270 EXPECT_GT(name_len, 0u);
1271 EXPECT_NE(999u, name_len);
Henrique Nakashimacf403ba2018-07-13 20:12:41 +00001272 std::wstring name =
1273 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
1274 if (name == L"Square") {
1275 // Verify the "Factor" parameter is still gone.
1276 int out_value;
1277 EXPECT_FALSE(
1278 FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
1279
1280 ++square_count;
1281 }
1282 }
1283 }
1284
1285 // Verify the parameters are gone, but the marks are not.
1286 EXPECT_EQ(4u, square_count);
1287
1288 CloseSavedPage(saved_page);
1289 CloseSavedDocument();
1290}
1291
Lei Zhangab41f252018-12-23 03:10:50 +00001292TEST_F(FPDFEditEmbedderTest, MaintainMarkedObjects) {
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001293 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001294 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001295 FPDF_PAGE page = LoadPage(0);
1296 ASSERT_TRUE(page);
1297
1298 // Iterate over all objects, counting the number of times each content mark
1299 // name appears.
1300 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
1301
1302 // Remove first page object.
1303 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1304 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1305 FPDFPageObj_Destroy(page_object);
1306
1307 CheckMarkCounts(page, 2, 18, 8, 3, 9, 1);
1308
1309 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1310 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1311
1312 UnloadPage(page);
1313
Lei Zhang0b494052019-01-31 21:41:15 +00001314 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001315 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001316 ASSERT_TRUE(saved_page);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001317
1318 CheckMarkCounts(saved_page, 2, 18, 8, 3, 9, 1);
1319
1320 CloseSavedPage(saved_page);
1321 CloseSavedDocument();
1322}
1323
Lei Zhangab41f252018-12-23 03:10:50 +00001324TEST_F(FPDFEditEmbedderTest, MaintainIndirectMarkedObjects) {
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001325 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001326 ASSERT_TRUE(OpenDocument("text_in_page_marked_indirect.pdf"));
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001327 FPDF_PAGE page = LoadPage(0);
1328 ASSERT_TRUE(page);
1329
1330 // Iterate over all objects, counting the number of times each content mark
1331 // name appears.
1332 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
1333
1334 // Remove first page object.
1335 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1336 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1337 FPDFPageObj_Destroy(page_object);
1338
1339 CheckMarkCounts(page, 2, 18, 8, 3, 9, 1);
1340
1341 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1342 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1343
1344 UnloadPage(page);
1345
Lei Zhang0b494052019-01-31 21:41:15 +00001346 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001347 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001348 ASSERT_TRUE(saved_page);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00001349
1350 CheckMarkCounts(saved_page, 2, 18, 8, 3, 9, 1);
1351
1352 CloseSavedPage(saved_page);
1353 CloseSavedDocument();
1354}
1355
Lei Zhangab41f252018-12-23 03:10:50 +00001356TEST_F(FPDFEditEmbedderTest, RemoveExistingPageObject) {
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001357 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001358 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001359 FPDF_PAGE page = LoadPage(0);
1360 ASSERT_TRUE(page);
1361
1362 // Get the "Hello, world!" text object and remove it.
1363 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1364 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1365 ASSERT_TRUE(page_object);
1366 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1367
1368 // Verify the "Hello, world!" text is gone.
1369 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1370
1371 // Save the file
1372 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1373 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1374 UnloadPage(page);
1375 FPDFPageObj_Destroy(page_object);
1376
1377 // Re-open the file and check the page object count is still 1.
Lei Zhang0b494052019-01-31 21:41:15 +00001378 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001379 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001380 ASSERT_TRUE(saved_page);
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001381 EXPECT_EQ(1, FPDFPage_CountObjects(saved_page));
1382 CloseSavedPage(saved_page);
1383 CloseSavedDocument();
1384}
1385
Hui Yingstcb4203d2020-06-09 01:48:47 +00001386TEST_F(FPDFEditEmbedderTest, RemoveExistingPageObjectSplitStreamsNotLonely) {
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001387 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001388 ASSERT_TRUE(OpenDocument("hello_world_split_streams.pdf"));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001389 FPDF_PAGE page = LoadPage(0);
1390 ASSERT_TRUE(page);
1391
1392 // Get the "Hello, world!" text object and remove it. There is another object
1393 // in the same stream that says "Goodbye, world!"
1394 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1395 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1396 ASSERT_TRUE(page_object);
1397 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1398
1399 // Verify the "Hello, world!" text is gone.
1400 ASSERT_EQ(2, FPDFPage_CountObjects(page));
Hui Yingstcb4203d2020-06-09 01:48:47 +00001401#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00001402 const char kHelloRemovedChecksum[] = "fc2a40a3d1edfe6e972be104b5ae87ad";
Lei Zhang42d30c22022-01-12 19:24:43 +00001403#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00001404 const char kHelloRemovedChecksum[] = "5508c2f06d104050f74f655693e38c2c";
Hui Yingstcb4203d2020-06-09 01:48:47 +00001405#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00001406 const char kHelloRemovedChecksum[] = "a8cd82499cf744e0862ca468c9d4ceb8";
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001407#endif
1408 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001409 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstcb4203d2020-06-09 01:48:47 +00001410 CompareBitmap(page_bitmap.get(), 200, 200, kHelloRemovedChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001411 }
1412
1413 // Save the file
1414 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1415 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1416 UnloadPage(page);
1417 FPDFPageObj_Destroy(page_object);
1418
1419 // Re-open the file and check the page object count is still 2.
Lei Zhang0b494052019-01-31 21:41:15 +00001420 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001421 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001422 ASSERT_TRUE(saved_page);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001423
1424 EXPECT_EQ(2, FPDFPage_CountObjects(saved_page));
1425 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001426 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstcb4203d2020-06-09 01:48:47 +00001427 CompareBitmap(page_bitmap.get(), 200, 200, kHelloRemovedChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001428 }
1429
1430 CloseSavedPage(saved_page);
1431 CloseSavedDocument();
1432}
1433
Hui Yingst08c40712020-04-29 01:37:35 +00001434TEST_F(FPDFEditEmbedderTest, RemoveExistingPageObjectSplitStreamsLonely) {
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001435 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001436 ASSERT_TRUE(OpenDocument("hello_world_split_streams.pdf"));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001437 FPDF_PAGE page = LoadPage(0);
1438 ASSERT_TRUE(page);
1439
1440 // Get the "Greetings, world!" text object and remove it. This is the only
1441 // object in the stream.
1442 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1443 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 2);
1444 ASSERT_TRUE(page_object);
1445 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1446
1447 // Verify the "Greetings, world!" text is gone.
1448 ASSERT_EQ(2, FPDFPage_CountObjects(page));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001449 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001450 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001451 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001452 }
1453
1454 // Save the file
1455 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1456 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1457 UnloadPage(page);
1458 FPDFPageObj_Destroy(page_object);
1459
1460 // Re-open the file and check the page object count is still 2.
Lei Zhang0b494052019-01-31 21:41:15 +00001461 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001462 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001463 ASSERT_TRUE(saved_page);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001464
1465 EXPECT_EQ(2, FPDFPage_CountObjects(saved_page));
1466 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001467 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001468 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001469 }
1470
1471 CloseSavedPage(saved_page);
1472 CloseSavedDocument();
1473}
1474
Lei Zhangab41f252018-12-23 03:10:50 +00001475TEST_F(FPDFEditEmbedderTest, GetContentStream) {
Henrique Nakashima6eb79392018-06-12 20:27:35 +00001476 // Load document with some text split across streams.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001477 ASSERT_TRUE(OpenDocument("split_streams.pdf"));
Henrique Nakashima6eb79392018-06-12 20:27:35 +00001478 FPDF_PAGE page = LoadPage(0);
1479 ASSERT_TRUE(page);
1480
1481 // Content stream 0: page objects 0-14.
1482 // Content stream 1: page objects 15-17.
1483 // Content stream 2: page object 18.
1484 ASSERT_EQ(19, FPDFPage_CountObjects(page));
1485 for (int i = 0; i < 19; i++) {
1486 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1487 ASSERT_TRUE(page_object);
1488 CPDF_PageObject* cpdf_page_object =
1489 CPDFPageObjectFromFPDFPageObject(page_object);
1490 if (i < 15)
1491 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1492 else if (i < 18)
1493 EXPECT_EQ(1, cpdf_page_object->GetContentStream()) << i;
1494 else
1495 EXPECT_EQ(2, cpdf_page_object->GetContentStream()) << i;
1496 }
1497
1498 UnloadPage(page);
1499}
1500
Hui Yingst0d692fe2020-11-06 17:32:50 +00001501TEST_F(FPDFEditEmbedderTest, RemoveAllFromStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001502 // Load document with some text split across streams.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001503 ASSERT_TRUE(OpenDocument("split_streams.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001504 FPDF_PAGE page = LoadPage(0);
1505 ASSERT_TRUE(page);
1506
1507 // Content stream 0: page objects 0-14.
1508 // Content stream 1: page objects 15-17.
1509 // Content stream 2: page object 18.
1510 ASSERT_EQ(19, FPDFPage_CountObjects(page));
1511
1512 // Loop backwards because objects will being removed, which shifts the indexes
1513 // after the removed position.
1514 for (int i = 18; i >= 0; i--) {
1515 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1516 ASSERT_TRUE(page_object);
1517 CPDF_PageObject* cpdf_page_object =
1518 CPDFPageObjectFromFPDFPageObject(page_object);
1519
1520 // Empty content stream 1.
1521 if (cpdf_page_object->GetContentStream() == 1) {
1522 EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
1523 FPDFPageObj_Destroy(page_object);
1524 }
1525 }
1526
1527 // Content stream 0: page objects 0-14.
1528 // Content stream 2: page object 15.
1529 ASSERT_EQ(16, FPDFPage_CountObjects(page));
1530 for (int i = 0; i < 16; i++) {
1531 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1532 ASSERT_TRUE(page_object);
1533 CPDF_PageObject* cpdf_page_object =
1534 CPDFPageObjectFromFPDFPageObject(page_object);
1535 if (i < 15)
1536 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1537 else
1538 EXPECT_EQ(2, cpdf_page_object->GetContentStream()) << i;
1539 }
1540
1541 // Generate contents should remove the empty stream and update the page
1542 // objects' contents stream indexes.
1543 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1544
1545 // Content stream 0: page objects 0-14.
1546 // Content stream 1: page object 15.
1547 ASSERT_EQ(16, FPDFPage_CountObjects(page));
1548 for (int i = 0; i < 16; i++) {
1549 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1550 ASSERT_TRUE(page_object);
1551 CPDF_PageObject* cpdf_page_object =
1552 CPDFPageObjectFromFPDFPageObject(page_object);
1553 if (i < 15)
1554 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1555 else
1556 EXPECT_EQ(1, cpdf_page_object->GetContentStream()) << i;
1557 }
1558
Hui Yingst0d692fe2020-11-06 17:32:50 +00001559#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00001560 const char kStream1RemovedChecksum[] = "7fe07f182b37d40afc6ae36a4e89fe73";
Lei Zhang42d30c22022-01-12 19:24:43 +00001561#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00001562 const char kStream1RemovedChecksum[] = "3cdc75af44c15bed80998facd6e674c9";
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001563#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00001564 const char kStream1RemovedChecksum[] = "b474826df1acedb05c7b82e1e49e64a6";
1565#endif
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001566 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001567 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst0d692fe2020-11-06 17:32:50 +00001568 CompareBitmap(page_bitmap.get(), 200, 200, kStream1RemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001569 }
1570
1571 // Save the file
1572 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1573 UnloadPage(page);
1574
1575 // Re-open the file and check the page object count is still 16, and that
1576 // content stream 1 was removed.
Lei Zhang0b494052019-01-31 21:41:15 +00001577 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001578 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001579 ASSERT_TRUE(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001580
1581 // Content stream 0: page objects 0-14.
1582 // Content stream 1: page object 15.
1583 EXPECT_EQ(16, FPDFPage_CountObjects(saved_page));
1584 for (int i = 0; i < 16; i++) {
1585 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(saved_page, i);
1586 ASSERT_TRUE(page_object);
1587 CPDF_PageObject* cpdf_page_object =
1588 CPDFPageObjectFromFPDFPageObject(page_object);
1589 if (i < 15)
1590 EXPECT_EQ(0, cpdf_page_object->GetContentStream()) << i;
1591 else
1592 EXPECT_EQ(1, cpdf_page_object->GetContentStream()) << i;
1593 }
1594
1595 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001596 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingst0d692fe2020-11-06 17:32:50 +00001597 CompareBitmap(page_bitmap.get(), 200, 200, kStream1RemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001598 }
1599
1600 CloseSavedPage(saved_page);
1601 CloseSavedDocument();
1602}
1603
Lei Zhangab41f252018-12-23 03:10:50 +00001604TEST_F(FPDFEditEmbedderTest, RemoveAllFromSingleStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001605 // Load document with a single stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001606 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001607 FPDF_PAGE page = LoadPage(0);
1608 ASSERT_TRUE(page);
1609
1610 // Content stream 0: page objects 0-1.
1611 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1612
1613 // Loop backwards because objects will being removed, which shifts the indexes
1614 // after the removed position.
1615 for (int i = 1; i >= 0; i--) {
1616 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1617 ASSERT_TRUE(page_object);
1618 CPDF_PageObject* cpdf_page_object =
1619 CPDFPageObjectFromFPDFPageObject(page_object);
1620 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1621 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1622 FPDFPageObj_Destroy(page_object);
1623 }
1624
1625 // No more objects in the stream
1626 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1627
1628 // Generate contents should remove the empty stream and update the page
1629 // objects' contents stream indexes.
1630 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1631
1632 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1633
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001634 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001635 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001636 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001637 }
1638
1639 // Save the file
1640 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1641 UnloadPage(page);
1642
1643 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001644 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001645 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001646 ASSERT_TRUE(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001647
1648 EXPECT_EQ(0, FPDFPage_CountObjects(saved_page));
1649 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001650 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001651 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001652 }
1653
1654 CloseSavedPage(saved_page);
1655 CloseSavedDocument();
1656}
1657
Hui Yingst08c40712020-04-29 01:37:35 +00001658TEST_F(FPDFEditEmbedderTest, RemoveFirstFromSingleStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001659 // Load document with a single stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001660 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001661 FPDF_PAGE page = LoadPage(0);
1662 ASSERT_TRUE(page);
1663
1664 // Content stream 0: page objects 0-1.
1665 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1666
1667 // Remove first object.
1668 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
1669 ASSERT_TRUE(page_object);
1670 CPDF_PageObject* cpdf_page_object =
1671 CPDFPageObjectFromFPDFPageObject(page_object);
1672 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1673 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1674 FPDFPageObj_Destroy(page_object);
1675
1676 // One object left in the stream.
1677 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1678 page_object = FPDFPage_GetObject(page, 0);
1679 ASSERT_TRUE(page_object);
1680 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1681 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1682
1683 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1684
1685 // Still one object left in the stream.
1686 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1687 page_object = FPDFPage_GetObject(page, 0);
1688 ASSERT_TRUE(page_object);
1689 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1690 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1691
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001692 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001693 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001694 CompareBitmap(page_bitmap.get(), 200, 200, kFirstRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001695 }
1696
1697 // Save the file
1698 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1699 UnloadPage(page);
1700
1701 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001702 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001703 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001704 ASSERT_TRUE(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001705
1706 ASSERT_EQ(1, FPDFPage_CountObjects(saved_page));
1707 page_object = FPDFPage_GetObject(saved_page, 0);
1708 ASSERT_TRUE(page_object);
1709 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1710 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1711 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001712 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001713 CompareBitmap(page_bitmap.get(), 200, 200, kFirstRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001714 }
1715
1716 CloseSavedPage(saved_page);
1717 CloseSavedDocument();
1718}
1719
Hui Yingst08c40712020-04-29 01:37:35 +00001720TEST_F(FPDFEditEmbedderTest, RemoveLastFromSingleStream) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001721 // Load document with a single stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001722 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001723 FPDF_PAGE page = LoadPage(0);
1724 ASSERT_TRUE(page);
1725
1726 // Content stream 0: page objects 0-1.
1727 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1728
1729 // Remove last object
1730 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 1);
1731 ASSERT_TRUE(page_object);
1732 CPDF_PageObject* cpdf_page_object =
1733 CPDFPageObjectFromFPDFPageObject(page_object);
1734 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1735 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1736 FPDFPageObj_Destroy(page_object);
1737
1738 // One object left in the stream.
1739 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1740 page_object = FPDFPage_GetObject(page, 0);
1741 ASSERT_TRUE(page_object);
1742 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1743 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1744
1745 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1746
1747 // Still one object left in the stream.
1748 ASSERT_EQ(1, FPDFPage_CountObjects(page));
1749 page_object = FPDFPage_GetObject(page, 0);
1750 ASSERT_TRUE(page_object);
1751 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1752 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1753
Hui Yingstb4baceb2020-04-28 23:46:10 +00001754 using pdfium::kHelloWorldRemovedChecksum;
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001755 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001756 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001757 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001758 }
1759
1760 // Save the file
1761 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1762 UnloadPage(page);
1763
1764 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001765 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001766 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001767 ASSERT_TRUE(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001768
1769 ASSERT_EQ(1, FPDFPage_CountObjects(saved_page));
1770 page_object = FPDFPage_GetObject(saved_page, 0);
1771 ASSERT_TRUE(page_object);
1772 cpdf_page_object = CPDFPageObjectFromFPDFPageObject(page_object);
1773 ASSERT_EQ(0, cpdf_page_object->GetContentStream());
1774 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001775 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001776 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001777 }
1778
1779 CloseSavedPage(saved_page);
1780 CloseSavedDocument();
1781}
1782
Lei Zhangab41f252018-12-23 03:10:50 +00001783TEST_F(FPDFEditEmbedderTest, RemoveAllFromMultipleStreams) {
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001784 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001785 ASSERT_TRUE(OpenDocument("hello_world_split_streams.pdf"));
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001786 FPDF_PAGE page = LoadPage(0);
1787 ASSERT_TRUE(page);
1788
1789 // Content stream 0: page objects 0-1.
1790 // Content stream 1: page object 2.
1791 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1792
1793 // Loop backwards because objects will being removed, which shifts the indexes
1794 // after the removed position.
1795 for (int i = 2; i >= 0; i--) {
1796 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
1797 ASSERT_TRUE(page_object);
1798 ASSERT_TRUE(FPDFPage_RemoveObject(page, page_object));
1799 FPDFPageObj_Destroy(page_object);
1800 }
1801
1802 // No more objects in the page.
1803 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1804
1805 // Generate contents should remove the empty streams and update the page
1806 // objects' contents stream indexes.
1807 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1808
1809 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1810
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001811 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001812 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001813 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001814 }
1815
1816 // Save the file
1817 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1818 UnloadPage(page);
1819
1820 // Re-open the file and check the page object count is still 0.
Lei Zhang0b494052019-01-31 21:41:15 +00001821 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001822 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001823 ASSERT_TRUE(saved_page);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001824
1825 EXPECT_EQ(0, FPDFPage_CountObjects(saved_page));
1826 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001827 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00001828 CompareBitmap(page_bitmap.get(), 200, 200, kAllRemovedChecksum);
Henrique Nakashima0dcf1f42018-06-21 18:51:15 +00001829 }
1830
1831 CloseSavedPage(saved_page);
1832 CloseSavedDocument();
1833}
1834
Lei Zhangab41f252018-12-23 03:10:50 +00001835TEST_F(FPDFEditEmbedderTest, InsertPageObjectAndSave) {
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001836 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001837 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001838 FPDF_PAGE page = LoadPage(0);
1839 ASSERT_TRUE(page);
1840
1841 // Add a red rectangle.
1842 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1843 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001844 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001845 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
1846 FPDFPage_InsertObject(page, red_rect);
1847
1848 // Verify the red rectangle was added.
1849 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1850
1851 // Save the file
1852 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1853 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1854 UnloadPage(page);
1855
1856 // Re-open the file and check the page object count is still 3.
Lei Zhang0b494052019-01-31 21:41:15 +00001857 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001858 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001859 ASSERT_TRUE(saved_page);
Henrique Nakashimac49e62e2018-04-16 20:58:47 +00001860 EXPECT_EQ(3, FPDFPage_CountObjects(saved_page));
1861 CloseSavedPage(saved_page);
1862 CloseSavedDocument();
1863}
1864
Lei Zhangab41f252018-12-23 03:10:50 +00001865TEST_F(FPDFEditEmbedderTest, InsertPageObjectEditAndSave) {
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001866 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001867 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001868 FPDF_PAGE page = LoadPage(0);
1869 ASSERT_TRUE(page);
1870
1871 // Add a red rectangle.
1872 ASSERT_EQ(2, FPDFPage_CountObjects(page));
1873 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001874 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 100, 100, 255));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001875 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
1876 FPDFPage_InsertObject(page, red_rect);
1877
1878 // Verify the red rectangle was added.
1879 ASSERT_EQ(3, FPDFPage_CountObjects(page));
1880
1881 // Generate content but change it again
1882 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhang3475b482019-05-13 18:30:57 +00001883 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001884
1885 // Save the file
1886 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1887 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1888 UnloadPage(page);
1889
1890 // Re-open the file and check the page object count is still 3.
Lei Zhang0b494052019-01-31 21:41:15 +00001891 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001892 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001893 ASSERT_TRUE(saved_page);
Henrique Nakashima27cf78d2018-06-14 16:22:30 +00001894 EXPECT_EQ(3, FPDFPage_CountObjects(saved_page));
1895 CloseSavedPage(saved_page);
1896 CloseSavedDocument();
1897}
1898
Hui Yingst8b5dfb22020-07-21 17:08:30 +00001899TEST_F(FPDFEditEmbedderTest, InsertAndRemoveLargeFile) {
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001900 const int kOriginalObjectCount = 600;
1901
1902 // Load document with many objects.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00001903 ASSERT_TRUE(OpenDocument("many_rectangles.pdf"));
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001904 FPDF_PAGE page = LoadPage(0);
1905 ASSERT_TRUE(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001906
1907 using pdfium::kManyRectanglesChecksum;
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001908 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001909 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001910 CompareBitmap(page_bitmap.get(), 200, 300, kManyRectanglesChecksum);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001911 }
1912
1913 // Add a black rectangle.
1914 ASSERT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(page));
1915 FPDF_PAGEOBJECT black_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00001916 EXPECT_TRUE(FPDFPageObj_SetFillColor(black_rect, 0, 0, 0, 255));
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001917 EXPECT_TRUE(FPDFPath_SetDrawMode(black_rect, FPDF_FILLMODE_ALTERNATE, 0));
1918 FPDFPage_InsertObject(page, black_rect);
1919
1920 // Verify the black rectangle was added.
1921 ASSERT_EQ(kOriginalObjectCount + 1, FPDFPage_CountObjects(page));
Hui Yingst8b5dfb22020-07-21 17:08:30 +00001922#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
1923 const char kPlusRectangleMD5[] = "0d3715fcfb9bd0dd25dcce60800bff47";
1924#else
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001925 const char kPlusRectangleMD5[] = "6b9396ab570754b32b04ca629e902f77";
Hui Yingst8b5dfb22020-07-21 17:08:30 +00001926#endif
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001927 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001928 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001929 CompareBitmap(page_bitmap.get(), 200, 300, kPlusRectangleMD5);
1930 }
1931
1932 // Save the file.
1933 EXPECT_TRUE(FPDFPage_GenerateContent(page));
1934 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
1935 UnloadPage(page);
1936
1937 // Re-open the file and check the rectangle added is still there.
Lei Zhang0b494052019-01-31 21:41:15 +00001938 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001939 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001940 ASSERT_TRUE(saved_page);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001941 EXPECT_EQ(kOriginalObjectCount + 1, FPDFPage_CountObjects(saved_page));
1942 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001943 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001944 CompareBitmap(page_bitmap.get(), 200, 300, kPlusRectangleMD5);
1945 }
1946
1947 // Remove the added rectangle.
1948 FPDF_PAGEOBJECT added_object =
1949 FPDFPage_GetObject(saved_page, kOriginalObjectCount);
1950 EXPECT_TRUE(FPDFPage_RemoveObject(saved_page, added_object));
1951 FPDFPageObj_Destroy(added_object);
1952 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001953 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001954 CompareBitmap(page_bitmap.get(), 200, 300, kManyRectanglesChecksum);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001955 }
1956 EXPECT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(saved_page));
1957
1958 // Save the file again.
1959 EXPECT_TRUE(FPDFPage_GenerateContent(saved_page));
Lei Zhang38e2b0e2021-11-05 00:28:05 +00001960 EXPECT_TRUE(FPDF_SaveAsCopy(saved_document(), this, 0));
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001961
1962 CloseSavedPage(saved_page);
1963 CloseSavedDocument();
1964
1965 // Re-open the file (again) and check the black rectangle was removed and the
1966 // rest is intact.
Lei Zhang0b494052019-01-31 21:41:15 +00001967 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001968 saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00001969 ASSERT_TRUE(saved_page);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001970 EXPECT_EQ(kOriginalObjectCount, FPDFPage_CountObjects(saved_page));
1971 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001972 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001973 CompareBitmap(page_bitmap.get(), 200, 300, kManyRectanglesChecksum);
Henrique Nakashima657a1aa2018-09-12 16:19:22 +00001974 }
1975
1976 CloseSavedPage(saved_page);
1977 CloseSavedDocument();
1978}
1979
Lei Zhangab41f252018-12-23 03:10:50 +00001980TEST_F(FPDFEditEmbedderTest, AddAndRemovePaths) {
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001981 // Start with a blank page.
1982 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
1983 ASSERT_TRUE(page);
1984
1985 // Render the blank page and verify it's a blank bitmap.
Hui Yingstb4baceb2020-04-28 23:46:10 +00001986 using pdfium::kBlankPage612By792Checksum;
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001987 {
Lei Zhang30ff2532019-01-31 21:37:55 +00001988 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00001989 CompareBitmap(page_bitmap.get(), 612, 792, kBlankPage612By792Checksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001990 }
1991 ASSERT_EQ(0, FPDFPage_CountObjects(page));
1992
1993 // Add a red rectangle.
1994 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
1995 ASSERT_TRUE(red_rect);
Lei Zhang3475b482019-05-13 18:30:57 +00001996 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001997 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
1998 FPDFPage_InsertObject(page, red_rect);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00001999 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002000 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00002001 CompareBitmap(page_bitmap.get(), 612, 792, kRedRectangleChecksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00002002 }
2003 EXPECT_EQ(1, FPDFPage_CountObjects(page));
2004
2005 // Remove rectangle and verify it does not render anymore and the bitmap is
2006 // back to a blank one.
2007 EXPECT_TRUE(FPDFPage_RemoveObject(page, red_rect));
2008 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002009 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00002010 CompareBitmap(page_bitmap.get(), 612, 792, kBlankPage612By792Checksum);
Henrique Nakashima35841fa2018-03-15 15:25:16 +00002011 }
2012 EXPECT_EQ(0, FPDFPage_CountObjects(page));
2013
2014 // Trying to remove an object not in the page should return false.
2015 EXPECT_FALSE(FPDFPage_RemoveObject(page, red_rect));
2016
2017 FPDF_ClosePage(page);
2018 FPDFPageObj_Destroy(red_rect);
2019}
2020
Lei Zhangab41f252018-12-23 03:10:50 +00002021TEST_F(FPDFEditEmbedderTest, PathsPoints) {
Miklos Vajna12abfd02017-09-15 07:49:03 +02002022 CreateNewDocument();
Lei Zhang38e2b0e2021-11-05 00:28:05 +00002023 FPDF_PAGEOBJECT img = FPDFPageObj_NewImageObj(document());
Miklos Vajna12abfd02017-09-15 07:49:03 +02002024 // This should fail gracefully, even if img is not a path.
Miklos Vajna0150a542017-09-21 21:46:56 +02002025 ASSERT_EQ(-1, FPDFPath_CountSegments(img));
Miklos Vajna12abfd02017-09-15 07:49:03 +02002026
2027 // This should fail gracefully, even if path is NULL.
Miklos Vajna0150a542017-09-21 21:46:56 +02002028 ASSERT_EQ(-1, FPDFPath_CountSegments(nullptr));
Miklos Vajna12abfd02017-09-15 07:49:03 +02002029
Miklos Vajna36eed872017-09-20 22:52:43 +02002030 // FPDFPath_GetPathSegment() with a non-path.
2031 ASSERT_EQ(nullptr, FPDFPath_GetPathSegment(img, 0));
2032 // FPDFPath_GetPathSegment() with a NULL path.
2033 ASSERT_EQ(nullptr, FPDFPath_GetPathSegment(nullptr, 0));
2034 float x;
2035 float y;
2036 // FPDFPathSegment_GetPoint() with a NULL segment.
2037 EXPECT_FALSE(FPDFPathSegment_GetPoint(nullptr, &x, &y));
2038
2039 // FPDFPathSegment_GetType() with a NULL segment.
2040 ASSERT_EQ(FPDF_SEGMENT_UNKNOWN, FPDFPathSegment_GetType(nullptr));
2041
2042 // FPDFPathSegment_GetClose() with a NULL segment.
2043 EXPECT_FALSE(FPDFPathSegment_GetClose(nullptr));
2044
Miklos Vajna12abfd02017-09-15 07:49:03 +02002045 FPDFPageObj_Destroy(img);
2046}
2047
Hui Yingste95d5772020-08-24 23:58:26 +00002048TEST_F(FPDFEditEmbedderTest, PathOnTopOfText) {
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002049 // Load document with some text
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002050 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002051 FPDF_PAGE page = LoadPage(0);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002052 ASSERT_TRUE(page);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002053
2054 // Add an opaque rectangle on top of some of the text.
2055 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002056 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002057 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
2058 FPDFPage_InsertObject(page, red_rect);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002059
2060 // Add a transparent triangle on top of other part of the text.
2061 FPDF_PAGEOBJECT black_path = FPDFPageObj_CreateNewPath(20, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002062 EXPECT_TRUE(FPDFPageObj_SetFillColor(black_path, 0, 0, 0, 100));
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002063 EXPECT_TRUE(FPDFPath_SetDrawMode(black_path, FPDF_FILLMODE_ALTERNATE, 0));
2064 EXPECT_TRUE(FPDFPath_LineTo(black_path, 30, 80));
2065 EXPECT_TRUE(FPDFPath_LineTo(black_path, 40, 10));
2066 EXPECT_TRUE(FPDFPath_Close(black_path));
2067 FPDFPage_InsertObject(page, black_path);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002068
Hui Yingste95d5772020-08-24 23:58:26 +00002069 // Render and check the result.
Tom Sepeze08d2b12018-04-25 18:49:32 +00002070 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
Hui Yingste95d5772020-08-24 23:58:26 +00002071#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00002072 const char kChecksum[] = "3490f699d894351a554d79e1fcdf7981";
Lei Zhang42d30c22022-01-12 19:24:43 +00002073#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00002074 const char kChecksum[] = "279693baca9f48da2d75a8e289aed58e";
Hui Yingste95d5772020-08-24 23:58:26 +00002075#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00002076 const char kChecksum[] = "fe415d47945c10b9cc8e9ca08887369e";
Nicolas Pena5bcd9a32017-03-22 11:04:35 -04002077#endif
Hui Yingste95d5772020-08-24 23:58:26 +00002078 CompareBitmap(bitmap.get(), 200, 200, kChecksum);
Nicolas Pena0fc185e2017-02-08 12:13:20 -05002079 UnloadPage(page);
2080}
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002081
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002082TEST_F(FPDFEditEmbedderTest, EditOverExistingContent) {
wileyryae858aa42017-05-31 14:49:05 -05002083 // Load document with existing content
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002084 ASSERT_TRUE(OpenDocument("bug_717.pdf"));
wileyryae858aa42017-05-31 14:49:05 -05002085 FPDF_PAGE page = LoadPage(0);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002086 ASSERT_TRUE(page);
wileyryae858aa42017-05-31 14:49:05 -05002087
2088 // Add a transparent rectangle on top of the existing content
2089 FPDF_PAGEOBJECT red_rect2 = FPDFPageObj_CreateNewRect(90, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002090 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect2, 255, 0, 0, 100));
wileyryae858aa42017-05-31 14:49:05 -05002091 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect2, FPDF_FILLMODE_ALTERNATE, 0));
2092 FPDFPage_InsertObject(page, red_rect2);
2093
2094 // Add an opaque rectangle on top of the existing content
2095 FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(115, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002096 EXPECT_TRUE(FPDFPageObj_SetFillColor(red_rect, 255, 0, 0, 255));
wileyryae858aa42017-05-31 14:49:05 -05002097 EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
2098 FPDFPage_InsertObject(page, red_rect);
2099
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002100#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2101 const char kOriginalChecksum[] = "1e82fbdd21490cee9d3479fe6125af67";
2102#else
2103 const char kOriginalChecksum[] = "ad04e5bd0f471a9a564fb034bd0fb073";
2104#endif
Tom Sepeze08d2b12018-04-25 18:49:32 +00002105 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002106 CompareBitmap(bitmap.get(), 612, 792, kOriginalChecksum);
wileyryae858aa42017-05-31 14:49:05 -05002107 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2108
2109 // Now save the result, closing the page and document
2110 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Nicolas Pena3ff54002017-07-05 11:55:35 -04002111 UnloadPage(page);
wileyryae858aa42017-05-31 14:49:05 -05002112
Lei Zhang0b494052019-01-31 21:41:15 +00002113 ASSERT_TRUE(OpenSavedDocument());
Lei Zhang107fa7b2018-02-09 21:48:15 +00002114 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00002115 ASSERT_TRUE(saved_page);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002116 VerifySavedRendering(saved_page, 612, 792, kOriginalChecksum);
wileyryae858aa42017-05-31 14:49:05 -05002117
2118 ClearString();
2119 // Add another opaque rectangle on top of the existing content
2120 FPDF_PAGEOBJECT green_rect = FPDFPageObj_CreateNewRect(150, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002121 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_rect, 0, 255, 0, 255));
wileyryae858aa42017-05-31 14:49:05 -05002122 EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect, FPDF_FILLMODE_ALTERNATE, 0));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002123 FPDFPage_InsertObject(saved_page, green_rect);
wileyryae858aa42017-05-31 14:49:05 -05002124
2125 // Add another transparent rectangle on top of existing content
2126 FPDF_PAGEOBJECT green_rect2 = FPDFPageObj_CreateNewRect(175, 700, 25, 50);
Lei Zhang3475b482019-05-13 18:30:57 +00002127 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_rect2, 0, 255, 0, 100));
wileyryae858aa42017-05-31 14:49:05 -05002128 EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect2, FPDF_FILLMODE_ALTERNATE, 0));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002129 FPDFPage_InsertObject(saved_page, green_rect2);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002130#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2131 const char kLastChecksum[] = "8705d023e5fec3499d1e30cf2bcc5dc1";
2132#else
2133 const char kLastChecksum[] = "4b5b00f824620f8c9b8801ebb98e1cdd";
2134#endif
Lei Zhangc113c7a2018-02-12 14:58:44 +00002135 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00002136 ScopedFPDFBitmap new_bitmap = RenderSavedPage(saved_page);
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002137 CompareBitmap(new_bitmap.get(), 612, 792, kLastChecksum);
Lei Zhangc113c7a2018-02-12 14:58:44 +00002138 }
Lei Zhang107fa7b2018-02-09 21:48:15 +00002139 EXPECT_TRUE(FPDFPage_GenerateContent(saved_page));
wileyryae858aa42017-05-31 14:49:05 -05002140
2141 // Now save the result, closing the page and document
Lei Zhang38e2b0e2021-11-05 00:28:05 +00002142 EXPECT_TRUE(FPDF_SaveAsCopy(saved_document(), this, 0));
Dan Sinclair04e4dc82017-10-18 12:17:14 -04002143
Lei Zhang107fa7b2018-02-09 21:48:15 +00002144 CloseSavedPage(saved_page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04002145 CloseSavedDocument();
wileyryae858aa42017-05-31 14:49:05 -05002146
2147 // Render the saved result
Hui Yingst1f73c4f2020-07-29 00:46:25 +00002148 VerifySavedDocument(612, 792, kLastChecksum);
wileyryae858aa42017-05-31 14:49:05 -05002149}
2150
Hui Yingst041116e2021-03-01 21:27:50 +00002151// TODO(crbug.com/pdfium/1651): Fix this issue and enable the test for Skia.
2152#if defined(_SKIA_SUPPORT_)
Lei Zhang03e5e682019-09-16 19:45:55 +00002153#define MAYBE_AddStrokedPaths DISABLED_AddStrokedPaths
2154#else
2155#define MAYBE_AddStrokedPaths AddStrokedPaths
2156#endif
2157TEST_F(FPDFEditEmbedderTest, MAYBE_AddStrokedPaths) {
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002158 // Start with a blank page
Nicolas Penad03ca422017-03-06 13:54:33 -05002159 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002160
2161 // Add a large stroked rectangle (fill color should not affect it).
2162 FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(20, 20, 200, 400);
Lei Zhang3475b482019-05-13 18:30:57 +00002163 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect, 255, 0, 0, 255));
2164 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(rect, 0, 255, 0, 255));
2165 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(rect, 15.0f));
Miklos Vajna366df7f2018-05-22 14:27:29 +00002166
2167 float width = 0;
2168 EXPECT_TRUE(FPDFPageObj_GetStrokeWidth(rect, &width));
2169 EXPECT_EQ(15.0f, width);
2170
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002171 EXPECT_TRUE(FPDFPath_SetDrawMode(rect, 0, 1));
2172 FPDFPage_InsertObject(page, rect);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002173 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002174 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst041116e2021-03-01 21:27:50 +00002175#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2176 static constexpr char kChecksum_1[] = "1469acf60e7647ebeb8e1fb08c5d6c7a";
2177#else
2178 static constexpr char kChecksum_1[] = "64bd31f862a89e0a9e505a5af6efd506";
2179#endif
2180 CompareBitmap(page_bitmap.get(), 612, 792, kChecksum_1);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002181 }
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002182
2183 // Add crossed-checkmark
2184 FPDF_PAGEOBJECT check = FPDFPageObj_CreateNewPath(300, 500);
2185 EXPECT_TRUE(FPDFPath_LineTo(check, 400, 400));
2186 EXPECT_TRUE(FPDFPath_LineTo(check, 600, 600));
2187 EXPECT_TRUE(FPDFPath_MoveTo(check, 400, 600));
2188 EXPECT_TRUE(FPDFPath_LineTo(check, 600, 400));
Lei Zhang3475b482019-05-13 18:30:57 +00002189 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(check, 128, 128, 128, 180));
2190 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(check, 8.35f));
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002191 EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1));
2192 FPDFPage_InsertObject(page, check);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002193 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002194 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst041116e2021-03-01 21:27:50 +00002195#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2196 static constexpr char kChecksum_2[] = "68b3194f74abd9d471695ce1415be43f";
2197#else
2198 static constexpr char kChecksum_2[] = "4b6f3b9d25c4e194821217d5016c3724";
2199#endif
2200 CompareBitmap(page_bitmap.get(), 612, 792, kChecksum_2);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002201 }
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002202
2203 // Add stroked and filled oval-ish path.
2204 FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(250, 100);
2205 EXPECT_TRUE(FPDFPath_BezierTo(path, 180, 166, 180, 233, 250, 300));
2206 EXPECT_TRUE(FPDFPath_LineTo(path, 255, 305));
2207 EXPECT_TRUE(FPDFPath_BezierTo(path, 325, 233, 325, 166, 255, 105));
2208 EXPECT_TRUE(FPDFPath_Close(path));
Lei Zhang3475b482019-05-13 18:30:57 +00002209 EXPECT_TRUE(FPDFPageObj_SetFillColor(path, 200, 128, 128, 100));
2210 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(path, 128, 200, 128, 150));
2211 EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(path, 10.5f));
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002212 EXPECT_TRUE(FPDFPath_SetDrawMode(path, FPDF_FILLMODE_ALTERNATE, 1));
2213 FPDFPage_InsertObject(page, path);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002214 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002215 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst041116e2021-03-01 21:27:50 +00002216#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
2217 static constexpr char kChecksum_3[] = "ea784068651df2b9ba132ce9215e6780";
2218#else
2219 static constexpr char kChecksum_3[] = "ff3e6a22326754944cc6e56609acd73b";
2220#endif
2221 CompareBitmap(page_bitmap.get(), 612, 792, kChecksum_3);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002222 }
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002223 FPDF_ClosePage(page);
Nicolas Pena2eb1a702017-02-09 18:17:33 -05002224}
Nicolas Pena49058402017-02-14 18:26:20 -05002225
Nicolas Pena4c48b102018-06-13 18:23:46 +00002226// Tests adding text from standard font using FPDFPageObj_NewTextObj.
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002227TEST_F(FPDFEditEmbedderTest, AddStandardFontText) {
Nicolas Pena49058402017-02-14 18:26:20 -05002228 // Start with a blank page
Lei Zhang8496d132021-07-08 04:34:34 +00002229 ScopedFPDFPage page(FPDFPage_New(CreateNewDocument(), 0, 612, 792));
Nicolas Pena49058402017-02-14 18:26:20 -05002230
2231 // Add some text to the page
Nicolas Penab3161852017-05-02 14:12:50 -04002232 FPDF_PAGEOBJECT text_object1 =
2233 FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
2234 EXPECT_TRUE(text_object1);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002235 ScopedFPDFWideString text1 = GetFPDFWideString(kBottomText);
Nicolas Penab3161852017-05-02 14:12:50 -04002236 EXPECT_TRUE(FPDFText_SetText(text_object1, text1.get()));
Lei Zhangcfd08172021-06-30 04:11:21 +00002237 static constexpr FS_MATRIX kMatrix1{1, 0, 0, 1, 20, 20};
2238 EXPECT_TRUE(FPDFPageObj_SetMatrix(text_object1, &kMatrix1));
Lei Zhang8496d132021-07-08 04:34:34 +00002239 FPDFPage_InsertObject(page.get(), text_object1);
2240 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002241 {
Lei Zhang8496d132021-07-08 04:34:34 +00002242 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
Hui Yingst3b6136a2020-06-09 00:39:33 +00002243 CompareBitmap(page_bitmap.get(), 612, 792, kBottomTextChecksum);
Lei Zhange039bab2019-03-18 19:57:56 +00002244
2245 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Hui Yingst3b6136a2020-06-09 00:39:33 +00002246 VerifySavedDocument(612, 792, kBottomTextChecksum);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002247 }
Nicolas Pena49058402017-02-14 18:26:20 -05002248
2249 // Try another font
Nicolas Penab3161852017-05-02 14:12:50 -04002250 FPDF_PAGEOBJECT text_object2 =
Nicolas Penad03ca422017-03-06 13:54:33 -05002251 FPDFPageObj_NewTextObj(document(), "TimesNewRomanBold", 15.0f);
Nicolas Penab3161852017-05-02 14:12:50 -04002252 EXPECT_TRUE(text_object2);
Lei Zhangf0f67682019-04-08 17:03:21 +00002253 ScopedFPDFWideString text2 =
Nicolas Penab3161852017-05-02 14:12:50 -04002254 GetFPDFWideString(L"Hi, I'm Bold. Times New Roman Bold.");
2255 EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
2256 FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 100, 600);
Lei Zhang8496d132021-07-08 04:34:34 +00002257 FPDFPage_InsertObject(page.get(), text_object2);
2258 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002259 {
Lei Zhang8496d132021-07-08 04:34:34 +00002260 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002261#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00002262 static constexpr char md5[] = "fa64eb3808b541342496281277fad5f2";
Nicolas Pena49058402017-02-14 18:26:20 -05002263#else
Lei Zhang42d30c22022-01-12 19:24:43 +00002264#if BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00002265 static constexpr char md5[] = "983baaa1f688eff7a14b1bf91c171a1a";
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002266#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00002267 static constexpr char md5[] = "161523e196eb5341604cd73e12c97922";
Nicolas Pena5bcd9a32017-03-22 11:04:35 -04002268#endif
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002269#endif // defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Lei Zhange039bab2019-03-18 19:57:56 +00002270 CompareBitmap(page_bitmap.get(), 612, 792, md5);
2271
2272 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2273 VerifySavedDocument(612, 792, md5);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002274 }
Nicolas Pena49058402017-02-14 18:26:20 -05002275
2276 // And some randomly transformed text
Nicolas Penab3161852017-05-02 14:12:50 -04002277 FPDF_PAGEOBJECT text_object3 =
Nicolas Penad03ca422017-03-06 13:54:33 -05002278 FPDFPageObj_NewTextObj(document(), "Courier-Bold", 20.0f);
Nicolas Penab3161852017-05-02 14:12:50 -04002279 EXPECT_TRUE(text_object3);
Lei Zhangf0f67682019-04-08 17:03:21 +00002280 ScopedFPDFWideString text3 = GetFPDFWideString(L"Can you read me? <:)>");
Nicolas Penab3161852017-05-02 14:12:50 -04002281 EXPECT_TRUE(FPDFText_SetText(text_object3, text3.get()));
2282 FPDFPageObj_Transform(text_object3, 1, 1.5, 2, 0.5, 200, 200);
Lei Zhang8496d132021-07-08 04:34:34 +00002283 FPDFPage_InsertObject(page.get(), text_object3);
2284 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhang107fa7b2018-02-09 21:48:15 +00002285 {
Lei Zhang8496d132021-07-08 04:34:34 +00002286 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002287#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00002288 static constexpr char md5[] = "abc65660389911aab95550ca8cd97a2b";
Lei Zhang42d30c22022-01-12 19:24:43 +00002289#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00002290 static constexpr char md5[] = "e0b3493c5c16e41d0d892ffb48e63fba";
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002291#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00002292 static constexpr char md5[] = "1fbf772dca8d82b960631e6683934964";
Nicolas Pena5bcd9a32017-03-22 11:04:35 -04002293#endif
Lei Zhange039bab2019-03-18 19:57:56 +00002294 CompareBitmap(page_bitmap.get(), 612, 792, md5);
2295
2296 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2297 VerifySavedDocument(612, 792, md5);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002298 }
Nicolas Pena49058402017-02-14 18:26:20 -05002299
Lei Zhang8da98232019-12-11 23:29:33 +00002300 FS_MATRIX matrix;
Lei Zhangc8601bf2021-06-29 23:19:27 +00002301 EXPECT_TRUE(FPDFPageObj_GetMatrix(text_object3, &matrix));
Lei Zhang8da98232019-12-11 23:29:33 +00002302 EXPECT_FLOAT_EQ(1.0f, matrix.a);
2303 EXPECT_FLOAT_EQ(1.5f, matrix.b);
2304 EXPECT_FLOAT_EQ(2.0f, matrix.c);
2305 EXPECT_FLOAT_EQ(0.5f, matrix.d);
2306 EXPECT_FLOAT_EQ(200.0f, matrix.e);
2307 EXPECT_FLOAT_EQ(200.0f, matrix.f);
Miklos Vajnac765d2a2018-06-19 15:45:42 +00002308
Miklos Vajnad6d7ca72021-06-22 16:27:21 +00002309 EXPECT_FALSE(FPDFTextObj_GetFontSize(nullptr, nullptr));
Lei Zhang8496d132021-07-08 04:34:34 +00002310 float size = 55;
2311 EXPECT_FALSE(FPDFTextObj_GetFontSize(nullptr, &size));
2312 EXPECT_EQ(55, size);
Miklos Vajnad6d7ca72021-06-22 16:27:21 +00002313 EXPECT_TRUE(FPDFTextObj_GetFontSize(text_object3, &size));
2314 EXPECT_EQ(20, size);
Miklos Vajna8625d3b2018-06-26 15:12:48 +00002315
Nicolas Pena49058402017-02-14 18:26:20 -05002316 // TODO(npm): Why are there issues with text rotated by 90 degrees?
2317 // TODO(npm): FPDF_SaveAsCopy not giving the desired result after this.
Nicolas Pena49058402017-02-14 18:26:20 -05002318}
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002319
Lei Zhang20c52152021-06-18 20:37:10 +00002320TEST_F(FPDFEditEmbedderTest, AddStandardFontTextOfSizeZero) {
2321 // Start with a blank page
2322 ScopedFPDFPage page(FPDFPage_New(CreateNewDocument(), 0, 612, 792));
2323
2324 // Add some text of size 0 to the page.
2325 FPDF_PAGEOBJECT text_object =
2326 FPDFPageObj_NewTextObj(document(), "Arial", 0.0f);
2327 EXPECT_TRUE(text_object);
2328 ScopedFPDFWideString text = GetFPDFWideString(kBottomText);
2329 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2330 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 20, 20);
2331
Miklos Vajnad6d7ca72021-06-22 16:27:21 +00002332 float size = -1; // Make sure 'size' gets changed.
2333 EXPECT_TRUE(FPDFTextObj_GetFontSize(text_object, &size));
2334 EXPECT_EQ(0.0f, size);
Lei Zhang20c52152021-06-18 20:37:10 +00002335
2336 FPDFPage_InsertObject(page.get(), text_object);
2337 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
2338 {
2339 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
2340 CompareBitmap(page_bitmap.get(), 612, 792,
2341 pdfium::kBlankPage612By792Checksum);
2342
2343 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2344 VerifySavedDocument(612, 792, pdfium::kBlankPage612By792Checksum);
2345 }
2346}
2347
Daniel Hosseinian8cb6a652019-12-18 00:50:41 +00002348TEST_F(FPDFEditEmbedderTest, GetTextRenderMode) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002349 ASSERT_TRUE(OpenDocument("text_render_mode.pdf"));
Miklos Vajna1448cc12018-07-03 13:52:33 +00002350 FPDF_PAGE page = LoadPage(0);
2351 ASSERT_TRUE(page);
2352 ASSERT_EQ(2, FPDFPage_CountObjects(page));
2353
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002354 EXPECT_EQ(FPDF_TEXTRENDERMODE_UNKNOWN,
Daniel Hosseinian8cb6a652019-12-18 00:50:41 +00002355 FPDFTextObj_GetTextRenderMode(nullptr));
Miklos Vajna1448cc12018-07-03 13:52:33 +00002356
2357 FPDF_PAGEOBJECT fill = FPDFPage_GetObject(page, 0);
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002358 EXPECT_EQ(FPDF_TEXTRENDERMODE_FILL, FPDFTextObj_GetTextRenderMode(fill));
Miklos Vajna1448cc12018-07-03 13:52:33 +00002359
2360 FPDF_PAGEOBJECT stroke = FPDFPage_GetObject(page, 1);
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002361 EXPECT_EQ(FPDF_TEXTRENDERMODE_STROKE, FPDFTextObj_GetTextRenderMode(stroke));
2362
2363 UnloadPage(page);
2364}
2365
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002366TEST_F(FPDFEditEmbedderTest, SetTextRenderMode) {
Hui Yingst609f7d62020-04-23 23:14:13 +00002367#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00002368 const char kOriginalChecksum[] = "bf87e8b36380ebd96ca429213fa23a09";
2369 const char kStrokeChecksum[] = "d16eb1bb4748eeb5fb801594da70d519";
Lei Zhang42d30c22022-01-12 19:24:43 +00002370#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00002371 const char kOriginalChecksum[] = "c488514ce0fc949069ff560407edacd2";
2372 const char kStrokeChecksum[] = "e06ee84aeebe926e8c980b7822027e8a";
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002373#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00002374 const char kOriginalChecksum[] = "97a4fcf3c9581e19917895631af31d41";
2375 const char kStrokeChecksum[] = "e06ee84aeebe926e8c980b7822027e8a";
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002376#endif
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002377
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002378 {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002379 ASSERT_TRUE(OpenDocument("text_render_mode.pdf"));
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002380 FPDF_PAGE page = LoadPage(0);
2381 ASSERT_TRUE(page);
2382 ASSERT_EQ(2, FPDFPage_CountObjects(page));
2383
2384 // Check the bitmap
2385 {
2386 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002387 CompareBitmap(page_bitmap.get(), 612, 446, kOriginalChecksum);
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002388 }
2389
2390 // Cannot set on a null object.
2391 EXPECT_FALSE(
2392 FPDFTextObj_SetTextRenderMode(nullptr, FPDF_TEXTRENDERMODE_UNKNOWN));
2393 EXPECT_FALSE(
2394 FPDFTextObj_SetTextRenderMode(nullptr, FPDF_TEXTRENDERMODE_INVISIBLE));
2395
2396 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
2397 ASSERT_TRUE(page_object);
2398 EXPECT_EQ(FPDF_TEXTRENDERMODE_FILL,
2399 FPDFTextObj_GetTextRenderMode(page_object));
2400
2401 // Cannot set UNKNOWN as a render mode.
2402 EXPECT_FALSE(FPDFTextObj_SetTextRenderMode(page_object,
2403 FPDF_TEXTRENDERMODE_UNKNOWN));
2404
2405 EXPECT_TRUE(
2406 FPDFTextObj_SetTextRenderMode(page_object, FPDF_TEXTRENDERMODE_STROKE));
2407 EXPECT_EQ(FPDF_TEXTRENDERMODE_STROKE,
2408 FPDFTextObj_GetTextRenderMode(page_object));
2409
2410 // Check that bitmap displays changed content
2411 {
2412 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002413 CompareBitmap(page_bitmap.get(), 612, 446, kStrokeChecksum);
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002414 }
2415
Daniel Hosseinianafd27502020-07-01 04:59:03 +00002416 // Save a copy.
2417 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2418 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
2419
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002420 UnloadPage(page);
Daniel Hosseiniane83d8b42020-01-08 00:26:15 +00002421 }
Miklos Vajna1448cc12018-07-03 13:52:33 +00002422
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002423 {
Daniel Hosseinianafd27502020-07-01 04:59:03 +00002424 // Open the saved copy and render it. Check that the changed text render
2425 // mode is kept in the saved copy.
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002426 ASSERT_TRUE(OpenSavedDocument());
2427 FPDF_PAGE saved_page = LoadSavedPage(0);
2428 ASSERT_TRUE(saved_page);
2429
2430 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(saved_page, 0);
2431 EXPECT_TRUE(page_object);
Daniel Hosseinianafd27502020-07-01 04:59:03 +00002432 EXPECT_EQ(FPDF_TEXTRENDERMODE_STROKE,
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002433 FPDFTextObj_GetTextRenderMode(page_object));
2434
2435 ScopedFPDFBitmap bitmap = RenderSavedPage(saved_page);
Hui Yingst9d8e5ec2020-07-30 22:33:22 +00002436 CompareBitmap(bitmap.get(), 612, 446, kStrokeChecksum);
Daniel Hosseiniana933ebf2020-01-31 21:28:25 +00002437
2438 CloseSavedPage(saved_page);
2439 CloseSavedDocument();
2440 }
Miklos Vajna1448cc12018-07-03 13:52:33 +00002441}
2442
Robert Collyer68a18a02021-09-14 01:48:22 +00002443TEST_F(FPDFEditEmbedderTest, TextFontProperties) {
2444 // bad object tests
2445 EXPECT_FALSE(FPDFTextObj_GetFont(nullptr));
2446 EXPECT_EQ(0U, FPDFFont_GetFontName(nullptr, nullptr, 5));
2447 EXPECT_EQ(-1, FPDFFont_GetFlags(nullptr));
2448 EXPECT_EQ(-1, FPDFFont_GetWeight(nullptr));
2449 EXPECT_FALSE(FPDFFont_GetItalicAngle(nullptr, nullptr));
2450 EXPECT_FALSE(FPDFFont_GetAscent(nullptr, 12.f, nullptr));
2451 EXPECT_FALSE(FPDFFont_GetDescent(nullptr, 12.f, nullptr));
2452 EXPECT_FALSE(FPDFFont_GetGlyphWidth(nullptr, 's', 12.f, nullptr));
2453 EXPECT_FALSE(FPDFFont_GetGlyphPath(nullptr, 's', 12.f));
2454
2455 // good object tests
2456 ASSERT_TRUE(OpenDocument("text_font.pdf"));
2457 FPDF_PAGE page = LoadPage(0);
2458 ASSERT_TRUE(page);
2459 ASSERT_EQ(1, FPDFPage_CountObjects(page));
2460 FPDF_PAGEOBJECT text = FPDFPage_GetObject(page, 0);
2461 ASSERT_TRUE(text);
2462 float font_size;
2463 ASSERT_TRUE(FPDFTextObj_GetFontSize(text, &font_size));
2464 FPDF_FONT font = FPDFTextObj_GetFont(text);
2465 ASSERT_TRUE(font);
2466
2467 // null return pointer tests
2468 EXPECT_FALSE(FPDFFont_GetItalicAngle(font, nullptr));
2469 EXPECT_FALSE(FPDFFont_GetAscent(font, font_size, nullptr));
2470 EXPECT_FALSE(FPDFFont_GetDescent(font, font_size, nullptr));
2471 EXPECT_FALSE(FPDFFont_GetGlyphWidth(font, 's', font_size, nullptr));
2472
2473 // correct property tests
2474 {
2475 EXPECT_EQ(4, FPDFFont_GetFlags(font));
2476 EXPECT_EQ(400, FPDFFont_GetWeight(font));
2477
2478 int angle;
2479 EXPECT_TRUE(FPDFFont_GetItalicAngle(font, &angle));
2480 EXPECT_EQ(0, angle);
2481
2482 float ascent;
2483 EXPECT_TRUE(FPDFFont_GetAscent(font, font_size, &ascent));
2484 EXPECT_FLOAT_EQ(891 * font_size / 1000.0f, ascent);
2485
2486 float descent;
2487 EXPECT_TRUE(FPDFFont_GetDescent(font, font_size, &descent));
2488 EXPECT_FLOAT_EQ(-216 * font_size / 1000.0f, descent);
2489
2490 float a12;
2491 float a24;
2492 EXPECT_TRUE(FPDFFont_GetGlyphWidth(font, 'a', 12.0f, &a12));
2493 EXPECT_FLOAT_EQ(a12, 5.316f);
2494 EXPECT_TRUE(FPDFFont_GetGlyphWidth(font, 'a', 24.0f, &a24));
2495 EXPECT_FLOAT_EQ(a24, 10.632f);
2496 }
2497
2498 {
2499 // FPDFFont_GetFontName() positive testing.
2500 unsigned long size = FPDFFont_GetFontName(font, nullptr, 0);
2501 const char kExpectedFontName[] = "Liberation Serif";
2502 ASSERT_EQ(sizeof(kExpectedFontName), size);
2503 std::vector<char> font_name(size);
2504 ASSERT_EQ(size, FPDFFont_GetFontName(font, font_name.data(), size));
2505 ASSERT_STREQ(kExpectedFontName, font_name.data());
2506
2507 // FPDFFont_GetFontName() negative testing.
2508 ASSERT_EQ(0U, FPDFFont_GetFontName(nullptr, nullptr, 0));
2509
2510 font_name.resize(2);
2511 font_name[0] = 'x';
2512 font_name[1] = '\0';
2513 size = FPDFFont_GetFontName(font, font_name.data(), font_name.size());
2514 ASSERT_EQ(sizeof(kExpectedFontName), size);
2515 ASSERT_STREQ("x", font_name.data());
2516 }
2517
2518 UnloadPage(page);
2519}
2520
2521TEST_F(FPDFEditEmbedderTest, GlyphPaths) {
2522 // bad glyphpath
2523 EXPECT_EQ(-1, FPDFGlyphPath_CountGlyphSegments(nullptr));
2524 EXPECT_FALSE(FPDFGlyphPath_GetGlyphPathSegment(nullptr, 1));
2525
2526 ASSERT_TRUE(OpenDocument("text_font.pdf"));
2527 FPDF_PAGE page = LoadPage(0);
2528 ASSERT_TRUE(page);
2529 ASSERT_EQ(1, FPDFPage_CountObjects(page));
2530 FPDF_PAGEOBJECT text = FPDFPage_GetObject(page, 0);
2531 ASSERT_TRUE(text);
2532 FPDF_FONT font = FPDFTextObj_GetFont(text);
2533 ASSERT_TRUE(font);
2534
2535 // good glyphpath
2536 FPDF_GLYPHPATH gpath = FPDFFont_GetGlyphPath(font, 's', 12.0f);
2537 ASSERT_TRUE(gpath);
2538
2539 int count = FPDFGlyphPath_CountGlyphSegments(gpath);
2540 ASSERT_GT(count, 0);
2541 EXPECT_FALSE(FPDFGlyphPath_GetGlyphPathSegment(gpath, -1));
2542 EXPECT_FALSE(FPDFGlyphPath_GetGlyphPathSegment(gpath, count));
2543
2544 FPDF_PATHSEGMENT segment = FPDFGlyphPath_GetGlyphPathSegment(gpath, 1);
2545 ASSERT_TRUE(segment);
2546 EXPECT_EQ(FPDF_SEGMENT_BEZIERTO, FPDFPathSegment_GetType(segment));
2547
2548 UnloadPage(page);
2549}
2550
Lei Zhang4363dab2021-06-24 19:23:09 +00002551TEST_F(FPDFEditEmbedderTest, FormGetObjects) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002552 ASSERT_TRUE(OpenDocument("form_object.pdf"));
Miklos Vajnab66077d2018-07-11 13:25:02 +00002553 FPDF_PAGE page = LoadPage(0);
2554 ASSERT_TRUE(page);
2555 ASSERT_EQ(1, FPDFPage_CountObjects(page));
2556
2557 FPDF_PAGEOBJECT form = FPDFPage_GetObject(page, 0);
Lei Zhang4363dab2021-06-24 19:23:09 +00002558 ASSERT_EQ(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(form));
Miklos Vajnab66077d2018-07-11 13:25:02 +00002559 ASSERT_EQ(-1, FPDFFormObj_CountObjects(nullptr));
2560 ASSERT_EQ(2, FPDFFormObj_CountObjects(form));
2561
Miklos Vajna1d273f12018-07-16 19:20:36 +00002562 // FPDFFormObj_GetObject() positive testing.
2563 FPDF_PAGEOBJECT text1 = FPDFFormObj_GetObject(form, 0);
2564 ASSERT_TRUE(text1);
2565 float left = 0;
2566 float bottom = 0;
2567 float right = 0;
2568 float top = 0;
2569 ASSERT_TRUE(FPDFPageObj_GetBounds(text1, &left, &bottom, &right, &top));
2570 ASSERT_EQ(271, static_cast<int>(top));
2571
2572 FPDF_PAGEOBJECT text2 = FPDFFormObj_GetObject(form, 1);
2573 ASSERT_TRUE(text2);
2574 ASSERT_TRUE(FPDFPageObj_GetBounds(text2, &left, &bottom, &right, &top));
2575 ASSERT_EQ(221, static_cast<int>(top));
2576
2577 // FPDFFormObj_GetObject() negative testing.
2578 ASSERT_EQ(nullptr, FPDFFormObj_GetObject(nullptr, 0));
2579 ASSERT_EQ(nullptr, FPDFFormObj_GetObject(form, -1));
2580 ASSERT_EQ(nullptr, FPDFFormObj_GetObject(form, 2));
2581
Lei Zhangc8601bf2021-06-29 23:19:27 +00002582 // FPDFPageObj_GetMatrix() positive testing for forms.
Lei Zhang8da98232019-12-11 23:29:33 +00002583 static constexpr FS_MATRIX kMatrix = {1.0f, 1.5f, 2.0f, 2.5f, 100.0f, 200.0f};
Lei Zhang2193da92021-06-30 01:03:07 +00002584 EXPECT_TRUE(FPDFPageObj_SetMatrix(form, &kMatrix));
Miklos Vajna46b43732018-08-14 19:15:43 +00002585
Lei Zhang8da98232019-12-11 23:29:33 +00002586 FS_MATRIX matrix;
Lei Zhangc8601bf2021-06-29 23:19:27 +00002587 EXPECT_TRUE(FPDFPageObj_GetMatrix(form, &matrix));
Lei Zhang8da98232019-12-11 23:29:33 +00002588 EXPECT_FLOAT_EQ(kMatrix.a, matrix.a);
2589 EXPECT_FLOAT_EQ(kMatrix.b, matrix.b);
2590 EXPECT_FLOAT_EQ(kMatrix.c, matrix.c);
2591 EXPECT_FLOAT_EQ(kMatrix.d, matrix.d);
2592 EXPECT_FLOAT_EQ(kMatrix.e, matrix.e);
2593 EXPECT_FLOAT_EQ(kMatrix.f, matrix.f);
Miklos Vajna46b43732018-08-14 19:15:43 +00002594
Lei Zhangc8601bf2021-06-29 23:19:27 +00002595 // FPDFPageObj_GetMatrix() negative testing for forms.
2596 EXPECT_FALSE(FPDFPageObj_GetMatrix(form, nullptr));
Miklos Vajna46b43732018-08-14 19:15:43 +00002597
Miklos Vajnab66077d2018-07-11 13:25:02 +00002598 UnloadPage(page);
2599}
2600
Lei Zhang4363dab2021-06-24 19:23:09 +00002601TEST_F(FPDFEditEmbedderTest, ModifyFormObject) {
2602#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00002603 const char kOrigChecksum[] = "e15086e54078e4d22fa3fb12105c579e";
2604 const char kNewChecksum[] = "7282fe98693c0a7ad2c1b3f3f9563977";
Lei Zhang42d30c22022-01-12 19:24:43 +00002605#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00002606 const char kOrigChecksum[] = "a637057185f50aac1aa5490f726aef95";
2607 const char kNewChecksum[] = "8ad9d79b02b609ff734e2a2195c96e2d";
Lei Zhang4363dab2021-06-24 19:23:09 +00002608#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00002609 const char kOrigChecksum[] = "34a9ec0a9581a7970e073c0bcc4ca676";
2610 const char kNewChecksum[] = "609b5632a21c886fa93182dbc290bf7a";
2611#endif
Lei Zhang4363dab2021-06-24 19:23:09 +00002612
2613 ASSERT_TRUE(OpenDocument("form_object.pdf"));
2614 FPDF_PAGE page = LoadPage(0);
2615 ASSERT_TRUE(page);
2616 ASSERT_EQ(1, FPDFPage_CountObjects(page));
2617
2618 {
2619 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
2620 CompareBitmap(bitmap.get(), 62, 69, kOrigChecksum);
2621 }
2622
2623 FPDF_PAGEOBJECT form = FPDFPage_GetObject(page, 0);
2624 ASSERT_EQ(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(form));
2625
Lei Zhang651113b2021-06-25 20:03:25 +00002626 FPDFPageObj_Transform(form, 0.5, 0, 0, 0.5, 0, 0);
Lei Zhang4363dab2021-06-24 19:23:09 +00002627 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2628
2629 {
2630 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
2631 CompareBitmap(bitmap.get(), 62, 69, kNewChecksum);
2632 }
2633
Lei Zhang4363dab2021-06-24 19:23:09 +00002634 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
Lei Zhangac7f0e12021-06-24 19:38:00 +00002635 VerifySavedDocument(62, 69, kNewChecksum);
Lei Zhang4363dab2021-06-24 19:23:09 +00002636
2637 UnloadPage(page);
2638}
2639
Nicolas Pena4c48b102018-06-13 18:23:46 +00002640// Tests adding text from standard font using FPDFText_LoadStandardFont.
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00002641TEST_F(FPDFEditEmbedderTest, AddStandardFontText2) {
Nicolas Pena4c48b102018-06-13 18:23:46 +00002642 // Start with a blank page
2643 ScopedFPDFPage page(FPDFPage_New(CreateNewDocument(), 0, 612, 792));
2644
2645 // Load a standard font.
Tom Sepezffff6c52019-07-30 21:56:19 +00002646 ScopedFPDFFont font(FPDFText_LoadStandardFont(document(), "Helvetica"));
Nicolas Pena4c48b102018-06-13 18:23:46 +00002647 ASSERT_TRUE(font);
2648
2649 // Add some text to the page.
2650 FPDF_PAGEOBJECT text_object =
Tom Sepezffff6c52019-07-30 21:56:19 +00002651 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
Nicolas Pena4c48b102018-06-13 18:23:46 +00002652 EXPECT_TRUE(text_object);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002653 ScopedFPDFWideString text = GetFPDFWideString(kBottomText);
Nicolas Pena4c48b102018-06-13 18:23:46 +00002654 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2655 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 20, 20);
2656 FPDFPage_InsertObject(page.get(), text_object);
Lei Zhang30ff2532019-01-31 21:37:55 +00002657 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
Hui Yingst3b6136a2020-06-09 00:39:33 +00002658 CompareBitmap(page_bitmap.get(), 612, 792, kBottomTextChecksum);
Nicolas Pena4c48b102018-06-13 18:23:46 +00002659}
2660
Lei Zhangab41f252018-12-23 03:10:50 +00002661TEST_F(FPDFEditEmbedderTest, LoadStandardFonts) {
Nicolas Pena4c48b102018-06-13 18:23:46 +00002662 CreateNewDocument();
Lei Zhang590f4242019-05-15 20:57:26 +00002663 static constexpr const char* kStandardFontNames[] = {
Lei Zhangd72fd582018-07-27 19:37:27 +00002664 "Arial",
2665 "Arial-Bold",
2666 "Arial-BoldItalic",
2667 "Arial-Italic",
2668 "Courier",
2669 "Courier-BoldOblique",
2670 "Courier-Oblique",
2671 "Courier-Bold",
2672 "CourierNew",
2673 "CourierNew-Bold",
2674 "CourierNew-BoldItalic",
2675 "CourierNew-Italic",
2676 "Helvetica",
2677 "Helvetica-Bold",
2678 "Helvetica-BoldOblique",
2679 "Helvetica-Oblique",
2680 "Symbol",
2681 "TimesNewRoman",
2682 "TimesNewRoman-Bold",
2683 "TimesNewRoman-BoldItalic",
2684 "TimesNewRoman-Italic",
2685 "ZapfDingbats"};
Lei Zhang590f4242019-05-15 20:57:26 +00002686 for (const char* font_name : kStandardFontNames) {
Tom Sepezffff6c52019-07-30 21:56:19 +00002687 ScopedFPDFFont font(FPDFText_LoadStandardFont(document(), font_name));
Nicolas Pena4c48b102018-06-13 18:23:46 +00002688 EXPECT_TRUE(font) << font_name << " should be considered a standard font.";
2689 }
Lei Zhang590f4242019-05-15 20:57:26 +00002690 static constexpr const char* kNotStandardFontNames[] = {
Nicolas Pena4c48b102018-06-13 18:23:46 +00002691 "Abcdefg", "ArialB", "Arial-Style",
2692 "Font Name", "FontArial", "NotAStandardFontName",
2693 "TestFontName", "Quack", "Symbol-Italic",
2694 "Zapf"};
Lei Zhang590f4242019-05-15 20:57:26 +00002695 for (const char* font_name : kNotStandardFontNames) {
Tom Sepezffff6c52019-07-30 21:56:19 +00002696 ScopedFPDFFont font(FPDFText_LoadStandardFont(document(), font_name));
Nicolas Pena4c48b102018-06-13 18:23:46 +00002697 EXPECT_FALSE(font) << font_name
2698 << " should not be considered a standard font.";
2699 }
2700}
2701
Lei Zhangab41f252018-12-23 03:10:50 +00002702TEST_F(FPDFEditEmbedderTest, GraphicsData) {
Nicolas Pena603a31d2017-06-14 11:41:18 -04002703 // New page
Tom Sepeze08d2b12018-04-25 18:49:32 +00002704 ScopedFPDFPage page(FPDFPage_New(CreateNewDocument(), 0, 612, 792));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002705
2706 // Create a rect with nontrivial graphics
2707 FPDF_PAGEOBJECT rect1 = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
2708 FPDFPageObj_SetBlendMode(rect1, "Color");
2709 FPDFPage_InsertObject(page.get(), rect1);
2710 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
2711
2712 // Check that the ExtGState was created
Lei Zhang107fa7b2018-02-09 21:48:15 +00002713 CPDF_Page* cpage = CPDFPageFromFPDFPage(page.get());
Tom Sepezc8155092021-04-26 23:37:42 +00002714 const CPDF_Dictionary* graphics_dict =
2715 cpage->GetResources()->GetDictFor("ExtGState");
Nicolas Pena603a31d2017-06-14 11:41:18 -04002716 ASSERT_TRUE(graphics_dict);
Lei Zhangf40380f2018-10-12 18:31:51 +00002717 EXPECT_EQ(2u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002718
2719 // Add a text object causing no change to the graphics dictionary
2720 FPDF_PAGEOBJECT text1 = FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
2721 // Only alpha, the last component, matters for the graphics dictionary. And
2722 // the default value is 255.
Lei Zhang3475b482019-05-13 18:30:57 +00002723 EXPECT_TRUE(FPDFPageObj_SetFillColor(text1, 100, 100, 100, 255));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002724 FPDFPage_InsertObject(page.get(), text1);
2725 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002726 EXPECT_EQ(2u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002727
2728 // Add a text object increasing the size of the graphics dictionary
2729 FPDF_PAGEOBJECT text2 =
2730 FPDFPageObj_NewTextObj(document(), "Times-Roman", 12.0f);
2731 FPDFPage_InsertObject(page.get(), text2);
2732 FPDFPageObj_SetBlendMode(text2, "Darken");
Lei Zhang3475b482019-05-13 18:30:57 +00002733 EXPECT_TRUE(FPDFPageObj_SetFillColor(text2, 0, 0, 255, 150));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002734 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002735 EXPECT_EQ(3u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002736
2737 // Add a path that should reuse graphics
Nicolas Penace67be42017-06-14 14:52:49 -04002738 FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(400, 100);
Nicolas Pena603a31d2017-06-14 11:41:18 -04002739 FPDFPageObj_SetBlendMode(path, "Darken");
Lei Zhang3475b482019-05-13 18:30:57 +00002740 EXPECT_TRUE(FPDFPageObj_SetFillColor(path, 200, 200, 100, 150));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002741 FPDFPage_InsertObject(page.get(), path);
2742 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002743 EXPECT_EQ(3u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002744
2745 // Add a rect increasing the size of the graphics dictionary
2746 FPDF_PAGEOBJECT rect2 = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
2747 FPDFPageObj_SetBlendMode(rect2, "Darken");
Lei Zhang3475b482019-05-13 18:30:57 +00002748 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect2, 0, 0, 255, 150));
2749 EXPECT_TRUE(FPDFPageObj_SetStrokeColor(rect2, 0, 0, 0, 200));
Nicolas Pena603a31d2017-06-14 11:41:18 -04002750 FPDFPage_InsertObject(page.get(), rect2);
2751 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
Lei Zhangf40380f2018-10-12 18:31:51 +00002752 EXPECT_EQ(4u, graphics_dict->size());
Nicolas Pena603a31d2017-06-14 11:41:18 -04002753}
2754
Lei Zhangab41f252018-12-23 03:10:50 +00002755TEST_F(FPDFEditEmbedderTest, DoubleGenerating) {
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002756 // Start with a blank page
Nicolas Penad03ca422017-03-06 13:54:33 -05002757 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002758
2759 // Add a red rectangle with some non-default alpha
2760 FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
Lei Zhang3475b482019-05-13 18:30:57 +00002761 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect, 255, 0, 0, 128));
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002762 EXPECT_TRUE(FPDFPath_SetDrawMode(rect, FPDF_FILLMODE_WINDING, 0));
2763 FPDFPage_InsertObject(page, rect);
2764 EXPECT_TRUE(FPDFPage_GenerateContent(page));
2765
2766 // Check the ExtGState
Lei Zhang107fa7b2018-02-09 21:48:15 +00002767 CPDF_Page* cpage = CPDFPageFromFPDFPage(page);
Tom Sepezc8155092021-04-26 23:37:42 +00002768 const CPDF_Dictionary* graphics_dict =
2769 cpage->GetResources()->GetDictFor("ExtGState");
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002770 ASSERT_TRUE(graphics_dict);
Lei Zhangf40380f2018-10-12 18:31:51 +00002771 EXPECT_EQ(2u, graphics_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002772
2773 // Check the bitmap
Lei Zhang107fa7b2018-02-09 21:48:15 +00002774 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002775 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002776 CompareBitmap(page_bitmap.get(), 612, 792,
2777 "5384da3406d62360ffb5cac4476fff1c");
2778 }
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002779
2780 // Never mind, my new favorite color is blue, increase alpha
Lei Zhang3475b482019-05-13 18:30:57 +00002781 EXPECT_TRUE(FPDFPageObj_SetFillColor(rect, 0, 0, 255, 180));
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002782 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhangf40380f2018-10-12 18:31:51 +00002783 EXPECT_EQ(3u, graphics_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002784
2785 // Check that bitmap displays changed content
Lei Zhang107fa7b2018-02-09 21:48:15 +00002786 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002787 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002788 CompareBitmap(page_bitmap.get(), 612, 792,
2789 "2e51656f5073b0bee611d9cd086aa09c");
2790 }
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002791
2792 // And now generate, without changes
2793 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhangf40380f2018-10-12 18:31:51 +00002794 EXPECT_EQ(3u, graphics_dict->size());
Lei Zhang107fa7b2018-02-09 21:48:15 +00002795 {
Lei Zhang30ff2532019-01-31 21:37:55 +00002796 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00002797 CompareBitmap(page_bitmap.get(), 612, 792,
2798 "2e51656f5073b0bee611d9cd086aa09c");
2799 }
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002800
2801 // Add some text to the page
Nicolas Penab3161852017-05-02 14:12:50 -04002802 FPDF_PAGEOBJECT text_object =
2803 FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
Lei Zhangf0f67682019-04-08 17:03:21 +00002804 ScopedFPDFWideString text =
Nicolas Penab3161852017-05-02 14:12:50 -04002805 GetFPDFWideString(L"Something something #text# something");
2806 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2807 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 300, 300);
2808 FPDFPage_InsertObject(page, text_object);
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002809 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Tom Sepezc8155092021-04-26 23:37:42 +00002810 const CPDF_Dictionary* font_dict = cpage->GetResources()->GetDictFor("Font");
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002811 ASSERT_TRUE(font_dict);
Lei Zhangf40380f2018-10-12 18:31:51 +00002812 EXPECT_EQ(1u, font_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002813
2814 // Generate yet again, check dicts are reasonably sized
2815 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Lei Zhangf40380f2018-10-12 18:31:51 +00002816 EXPECT_EQ(3u, graphics_dict->size());
2817 EXPECT_EQ(1u, font_dict->size());
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002818 FPDF_ClosePage(page);
Nicolas Penaa4ad01f2017-02-15 16:26:48 -05002819}
Nicolas Penabe90aae2017-02-27 10:41:41 -05002820
Lei Zhangab41f252018-12-23 03:10:50 +00002821TEST_F(FPDFEditEmbedderTest, LoadSimpleType1Font) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002822 CreateNewDocument();
2823 // TODO(npm): use other fonts after disallowing loading any font as any type
Tom Sepezffff6c52019-07-30 21:56:19 +00002824 RetainPtr<CPDF_Font> stock_font =
Nicolas Penad03ca422017-03-06 13:54:33 -05002825 CPDF_Font::GetStockFont(cpdf_doc(), "Times-Bold");
Tom Sepez20c41a52018-08-29 23:53:53 +00002826 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2827 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2828 FPDF_FONT_TYPE1, false));
Nicolas Penab3161852017-05-02 14:12:50 -04002829 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002830 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002831 EXPECT_TRUE(typed_font->IsType1Font());
Nicolas Penabe90aae2017-02-27 10:41:41 -05002832
Lei Zhang710fa992018-05-25 16:24:48 +00002833 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002834 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2835 EXPECT_EQ("Type1", font_dict->GetNameFor("Subtype"));
Tom Andersond4fe5f72021-12-03 20:52:52 +00002836 EXPECT_EQ("Tinos-Bold", font_dict->GetNameFor("BaseFont"));
Nicolas Penabe90aae2017-02-27 10:41:41 -05002837 ASSERT_TRUE(font_dict->KeyExist("FirstChar"));
2838 ASSERT_TRUE(font_dict->KeyExist("LastChar"));
2839 EXPECT_EQ(32, font_dict->GetIntegerFor("FirstChar"));
Nicolas Penad03ca422017-03-06 13:54:33 -05002840 EXPECT_EQ(255, font_dict->GetIntegerFor("LastChar"));
2841
Lei Zhangde579ab2018-05-25 21:49:49 +00002842 const CPDF_Array* widths_array = font_dict->GetArrayFor("Widths");
Nicolas Penad03ca422017-03-06 13:54:33 -05002843 ASSERT_TRUE(widths_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002844 ASSERT_EQ(224u, widths_array->size());
Nicolas Penabe90aae2017-02-27 10:41:41 -05002845 EXPECT_EQ(250, widths_array->GetNumberAt(0));
Nicolas Penad03ca422017-03-06 13:54:33 -05002846 EXPECT_EQ(569, widths_array->GetNumberAt(11));
2847 EXPECT_EQ(500, widths_array->GetNumberAt(223));
Tom Sepez20c41a52018-08-29 23:53:53 +00002848 CheckFontDescriptor(font_dict, FPDF_FONT_TYPE1, true, false, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05002849}
Nicolas Penabe90aae2017-02-27 10:41:41 -05002850
Lei Zhangab41f252018-12-23 03:10:50 +00002851TEST_F(FPDFEditEmbedderTest, LoadSimpleTrueTypeFont) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002852 CreateNewDocument();
Tom Sepezffff6c52019-07-30 21:56:19 +00002853 RetainPtr<CPDF_Font> stock_font =
2854 CPDF_Font::GetStockFont(cpdf_doc(), "Courier");
Tom Sepez20c41a52018-08-29 23:53:53 +00002855 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2856 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2857 FPDF_FONT_TRUETYPE, false));
Nicolas Penab3161852017-05-02 14:12:50 -04002858 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002859 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002860 EXPECT_TRUE(typed_font->IsTrueTypeFont());
Nicolas Penabe90aae2017-02-27 10:41:41 -05002861
Lei Zhang710fa992018-05-25 16:24:48 +00002862 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002863 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2864 EXPECT_EQ("TrueType", font_dict->GetNameFor("Subtype"));
Tom Andersond4fe5f72021-12-03 20:52:52 +00002865 EXPECT_EQ("Cousine-Regular", font_dict->GetNameFor("BaseFont"));
Nicolas Penad03ca422017-03-06 13:54:33 -05002866 ASSERT_TRUE(font_dict->KeyExist("FirstChar"));
2867 ASSERT_TRUE(font_dict->KeyExist("LastChar"));
2868 EXPECT_EQ(32, font_dict->GetIntegerFor("FirstChar"));
2869 EXPECT_EQ(255, font_dict->GetIntegerFor("LastChar"));
Nicolas Penabe90aae2017-02-27 10:41:41 -05002870
Lei Zhangde579ab2018-05-25 21:49:49 +00002871 const CPDF_Array* widths_array = font_dict->GetArrayFor("Widths");
Nicolas Penad03ca422017-03-06 13:54:33 -05002872 ASSERT_TRUE(widths_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002873 ASSERT_EQ(224u, widths_array->size());
Nicolas Penad03ca422017-03-06 13:54:33 -05002874 EXPECT_EQ(600, widths_array->GetNumberAt(33));
2875 EXPECT_EQ(600, widths_array->GetNumberAt(74));
2876 EXPECT_EQ(600, widths_array->GetNumberAt(223));
Tom Sepez20c41a52018-08-29 23:53:53 +00002877 CheckFontDescriptor(font_dict, FPDF_FONT_TRUETYPE, false, false, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05002878}
2879
Lei Zhangab41f252018-12-23 03:10:50 +00002880TEST_F(FPDFEditEmbedderTest, LoadCIDType0Font) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002881 CreateNewDocument();
Tom Sepezffff6c52019-07-30 21:56:19 +00002882 RetainPtr<CPDF_Font> stock_font =
Nicolas Penad03ca422017-03-06 13:54:33 -05002883 CPDF_Font::GetStockFont(cpdf_doc(), "Times-Roman");
Tom Sepez20c41a52018-08-29 23:53:53 +00002884 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2885 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2886 FPDF_FONT_TYPE1, 1));
Nicolas Penab3161852017-05-02 14:12:50 -04002887 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002888 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002889 EXPECT_TRUE(typed_font->IsCIDFont());
2890
2891 // Check font dictionary entries
Lei Zhang710fa992018-05-25 16:24:48 +00002892 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002893 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2894 EXPECT_EQ("Type0", font_dict->GetNameFor("Subtype"));
Tom Andersond4fe5f72021-12-03 20:52:52 +00002895 EXPECT_EQ("Tinos-Regular-Identity-H", font_dict->GetNameFor("BaseFont"));
Lei Zhanga228ff32020-06-24 17:39:33 +00002896 EXPECT_EQ("Identity-H", font_dict->GetNameFor("Encoding"));
Lei Zhangde579ab2018-05-25 21:49:49 +00002897 const CPDF_Array* descendant_array =
2898 font_dict->GetArrayFor("DescendantFonts");
Nicolas Penad03ca422017-03-06 13:54:33 -05002899 ASSERT_TRUE(descendant_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002900 EXPECT_EQ(1u, descendant_array->size());
Nicolas Penad03ca422017-03-06 13:54:33 -05002901
2902 // Check the CIDFontDict
Lei Zhangde579ab2018-05-25 21:49:49 +00002903 const CPDF_Dictionary* cidfont_dict = descendant_array->GetDictAt(0);
Lei Zhanga228ff32020-06-24 17:39:33 +00002904 EXPECT_EQ("Font", cidfont_dict->GetNameFor("Type"));
2905 EXPECT_EQ("CIDFontType0", cidfont_dict->GetNameFor("Subtype"));
Tom Andersond4fe5f72021-12-03 20:52:52 +00002906 EXPECT_EQ("Tinos-Regular", cidfont_dict->GetNameFor("BaseFont"));
Lei Zhangb1ec2802018-05-25 21:55:24 +00002907 const CPDF_Dictionary* cidinfo_dict =
2908 cidfont_dict->GetDictFor("CIDSystemInfo");
Nicolas Penad03ca422017-03-06 13:54:33 -05002909 ASSERT_TRUE(cidinfo_dict);
Lei Zhang9c950b12019-01-16 19:06:37 +00002910 const CPDF_Object* registry = cidinfo_dict->GetObjectFor("Registry");
2911 ASSERT_TRUE(registry);
KDr28da0e1b2019-01-17 03:44:29 +00002912 EXPECT_EQ(CPDF_Object::kString, registry->GetType());
Lei Zhang9c950b12019-01-16 19:06:37 +00002913 EXPECT_EQ("Adobe", registry->GetString());
2914 const CPDF_Object* ordering = cidinfo_dict->GetObjectFor("Ordering");
2915 ASSERT_TRUE(ordering);
KDr28da0e1b2019-01-17 03:44:29 +00002916 EXPECT_EQ(CPDF_Object::kString, ordering->GetType());
Lei Zhang9c950b12019-01-16 19:06:37 +00002917 EXPECT_EQ("Identity", ordering->GetString());
Nicolas Penad03ca422017-03-06 13:54:33 -05002918 EXPECT_EQ(0, cidinfo_dict->GetNumberFor("Supplement"));
Tom Sepez20c41a52018-08-29 23:53:53 +00002919 CheckFontDescriptor(cidfont_dict, FPDF_FONT_TYPE1, false, false, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05002920
2921 // Check widths
Lei Zhangde579ab2018-05-25 21:49:49 +00002922 const CPDF_Array* widths_array = cidfont_dict->GetArrayFor("W");
Nicolas Penad03ca422017-03-06 13:54:33 -05002923 ASSERT_TRUE(widths_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002924 EXPECT_GT(widths_array->size(), 1u);
Nicolas Penad03ca422017-03-06 13:54:33 -05002925 CheckCompositeFontWidths(widths_array, typed_font);
2926}
2927
Lei Zhangab41f252018-12-23 03:10:50 +00002928TEST_F(FPDFEditEmbedderTest, LoadCIDType2Font) {
Nicolas Penad03ca422017-03-06 13:54:33 -05002929 CreateNewDocument();
Tom Sepezffff6c52019-07-30 21:56:19 +00002930 RetainPtr<CPDF_Font> stock_font =
Nicolas Penad03ca422017-03-06 13:54:33 -05002931 CPDF_Font::GetStockFont(cpdf_doc(), "Helvetica-Oblique");
Tom Sepez20c41a52018-08-29 23:53:53 +00002932 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2933 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2934 FPDF_FONT_TRUETYPE, 1));
Nicolas Penab3161852017-05-02 14:12:50 -04002935 ASSERT_TRUE(font.get());
Tom Sepez525147a2018-05-03 17:19:53 +00002936 CPDF_Font* typed_font = CPDFFontFromFPDFFont(font.get());
Nicolas Penad03ca422017-03-06 13:54:33 -05002937 EXPECT_TRUE(typed_font->IsCIDFont());
2938
2939 // Check font dictionary entries
Lei Zhang710fa992018-05-25 16:24:48 +00002940 const CPDF_Dictionary* font_dict = typed_font->GetFontDict();
Lei Zhanga228ff32020-06-24 17:39:33 +00002941 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
2942 EXPECT_EQ("Type0", font_dict->GetNameFor("Subtype"));
Tom Andersond4fe5f72021-12-03 20:52:52 +00002943 EXPECT_EQ("Arimo-Italic", font_dict->GetNameFor("BaseFont"));
Lei Zhanga228ff32020-06-24 17:39:33 +00002944 EXPECT_EQ("Identity-H", font_dict->GetNameFor("Encoding"));
Lei Zhangde579ab2018-05-25 21:49:49 +00002945 const CPDF_Array* descendant_array =
2946 font_dict->GetArrayFor("DescendantFonts");
Nicolas Penad03ca422017-03-06 13:54:33 -05002947 ASSERT_TRUE(descendant_array);
Lei Zhangf40380f2018-10-12 18:31:51 +00002948 EXPECT_EQ(1u, descendant_array->size());
Nicolas Penad03ca422017-03-06 13:54:33 -05002949
2950 // Check the CIDFontDict
Lei Zhangde579ab2018-05-25 21:49:49 +00002951 const CPDF_Dictionary* cidfont_dict = descendant_array->GetDictAt(0);
Lei Zhanga228ff32020-06-24 17:39:33 +00002952 EXPECT_EQ("Font", cidfont_dict->GetNameFor("Type"));
2953 EXPECT_EQ("CIDFontType2", cidfont_dict->GetNameFor("Subtype"));
Tom Andersond4fe5f72021-12-03 20:52:52 +00002954 EXPECT_EQ("Arimo-Italic", cidfont_dict->GetNameFor("BaseFont"));
Lei Zhangb1ec2802018-05-25 21:55:24 +00002955 const CPDF_Dictionary* cidinfo_dict =
2956 cidfont_dict->GetDictFor("CIDSystemInfo");
Nicolas Penad03ca422017-03-06 13:54:33 -05002957 ASSERT_TRUE(cidinfo_dict);
2958 EXPECT_EQ("Adobe", cidinfo_dict->GetStringFor("Registry"));
2959 EXPECT_EQ("Identity", cidinfo_dict->GetStringFor("Ordering"));
2960 EXPECT_EQ(0, cidinfo_dict->GetNumberFor("Supplement"));
Tom Sepez20c41a52018-08-29 23:53:53 +00002961 CheckFontDescriptor(cidfont_dict, FPDF_FONT_TRUETYPE, false, true, span);
Nicolas Penad03ca422017-03-06 13:54:33 -05002962
2963 // Check widths
Lei Zhangde579ab2018-05-25 21:49:49 +00002964 const CPDF_Array* widths_array = cidfont_dict->GetArrayFor("W");
Nicolas Penad03ca422017-03-06 13:54:33 -05002965 ASSERT_TRUE(widths_array);
2966 CheckCompositeFontWidths(widths_array, typed_font);
Nicolas Penabe90aae2017-02-27 10:41:41 -05002967}
rbpotterce8e51e2017-04-28 12:42:47 -07002968
Lei Zhangab41f252018-12-23 03:10:50 +00002969TEST_F(FPDFEditEmbedderTest, NormalizeNegativeRotation) {
rbpotterce8e51e2017-04-28 12:42:47 -07002970 // Load document with a -90 degree rotation
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00002971 ASSERT_TRUE(OpenDocument("bug_713197.pdf"));
rbpotterce8e51e2017-04-28 12:42:47 -07002972 FPDF_PAGE page = LoadPage(0);
2973 EXPECT_NE(nullptr, page);
2974
2975 EXPECT_EQ(3, FPDFPage_GetRotation(page));
2976 UnloadPage(page);
2977}
Nicolas Penab3161852017-05-02 14:12:50 -04002978
Hui Yingst9d6ec8f2020-11-05 23:35:38 +00002979TEST_F(FPDFEditEmbedderTest, AddTrueTypeFontText) {
Nicolas Penab3161852017-05-02 14:12:50 -04002980 // Start with a blank page
2981 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
2982 {
Tom Sepezffff6c52019-07-30 21:56:19 +00002983 RetainPtr<CPDF_Font> stock_font =
2984 CPDF_Font::GetStockFont(cpdf_doc(), "Arial");
Tom Sepez20c41a52018-08-29 23:53:53 +00002985 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
2986 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
2987 FPDF_FONT_TRUETYPE, 0));
Nicolas Penab3161852017-05-02 14:12:50 -04002988 ASSERT_TRUE(font.get());
2989
2990 // Add some text to the page
2991 FPDF_PAGEOBJECT text_object =
2992 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
2993 EXPECT_TRUE(text_object);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002994 ScopedFPDFWideString text = GetFPDFWideString(kLoadedFontText);
Nicolas Penab3161852017-05-02 14:12:50 -04002995 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
2996 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 400, 400);
2997 FPDFPage_InsertObject(page, text_object);
Lei Zhang30ff2532019-01-31 21:37:55 +00002998 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00002999 CompareBitmap(page_bitmap.get(), 612, 792, kLoadedFontTextChecksum);
Nicolas Penab3161852017-05-02 14:12:50 -04003000
3001 // Add some more text, same font
3002 FPDF_PAGEOBJECT text_object2 =
3003 FPDFPageObj_CreateTextObj(document(), font.get(), 15.0f);
Lei Zhangf0f67682019-04-08 17:03:21 +00003004 ScopedFPDFWideString text2 = GetFPDFWideString(L"Bigger font size");
Nicolas Penab3161852017-05-02 14:12:50 -04003005 EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
3006 FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 200, 200);
3007 FPDFPage_InsertObject(page, text_object2);
Nicolas Penab3161852017-05-02 14:12:50 -04003008 }
Lei Zhang30ff2532019-01-31 21:37:55 +00003009 ScopedFPDFBitmap page_bitmap2 = RenderPage(page);
Hui Yingst9d6ec8f2020-11-05 23:35:38 +00003010#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00003011 const char kInsertTrueTypeChecksum[] = "4f9a6c7752ac7d4e4c731260fdb5af15";
Lei Zhang42d30c22022-01-12 19:24:43 +00003012#elif BUILDFLAG(IS_APPLE)
Tom Andersond4fe5f72021-12-03 20:52:52 +00003013 const char kInsertTrueTypeChecksum[] = "c7e2271a7f30e5b919a13ead47cea105";
Nicolas Penab3161852017-05-02 14:12:50 -04003014#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00003015 const char kInsertTrueTypeChecksum[] = "683f4a385a891494100192cb338b11f0";
Lei Zhange4cdac52019-04-30 16:45:57 +00003016#endif
Hui Yingst3b6136a2020-06-09 00:39:33 +00003017 CompareBitmap(page_bitmap2.get(), 612, 792, kInsertTrueTypeChecksum);
Nicolas Penab3161852017-05-02 14:12:50 -04003018
Nicolas Pena207b7272017-05-26 17:37:06 -04003019 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Nicolas Penab3161852017-05-02 14:12:50 -04003020 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3021 FPDF_ClosePage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04003022
Hui Yingst3b6136a2020-06-09 00:39:33 +00003023 VerifySavedDocument(612, 792, kInsertTrueTypeChecksum);
Nicolas Penab3161852017-05-02 14:12:50 -04003024}
Nicolas Penaf45ade32017-05-03 10:23:49 -04003025
Lei Zhangab41f252018-12-23 03:10:50 +00003026TEST_F(FPDFEditEmbedderTest, TransformAnnot) {
Jane Liueda65252017-06-07 11:31:27 -04003027 // Open a file with one annotation and load its first page.
3028 ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
Lei Zhang75c81712018-02-08 17:22:39 +00003029 FPDF_PAGE page = LoadPage(0);
Jane Liueda65252017-06-07 11:31:27 -04003030 ASSERT_TRUE(page);
3031
Lei Zhanga21d5932018-02-05 18:28:38 +00003032 {
3033 // Add an underline annotation to the page without specifying its rectangle.
Tom Sepeze08d2b12018-04-25 18:49:32 +00003034 ScopedFPDFAnnotation annot(
Lei Zhanga21d5932018-02-05 18:28:38 +00003035 FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE));
3036 ASSERT_TRUE(annot);
Jane Liueda65252017-06-07 11:31:27 -04003037
Lei Zhanga21d5932018-02-05 18:28:38 +00003038 // FPDFPage_TransformAnnots() should run without errors when modifying
3039 // annotation rectangles.
3040 FPDFPage_TransformAnnots(page, 1, 2, 3, 4, 5, 6);
3041 }
Jane Liueda65252017-06-07 11:31:27 -04003042 UnloadPage(page);
3043}
3044
Nicolas Penaf45ade32017-05-03 10:23:49 -04003045// TODO(npm): Add tests using Japanese fonts in other OS.
Lei Zhangeb2da2a2022-01-12 19:28:33 +00003046#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00003047TEST_F(FPDFEditEmbedderTest, AddCIDFontText) {
Nicolas Penaf45ade32017-05-03 10:23:49 -04003048 // Start with a blank page
3049 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
3050 CFX_Font CIDfont;
3051 {
3052 // First, get the data from the font
Tom Andersond4fe5f72021-12-03 20:52:52 +00003053 CIDfont.LoadSubst("Noto Sans CJK JP", 1, 0, 400, 0, FX_CodePage::kShiftJIS,
3054 0);
3055 EXPECT_EQ("Noto Sans CJK JP", CIDfont.GetFaceName());
Tom Sepez20c41a52018-08-29 23:53:53 +00003056 pdfium::span<const uint8_t> span = CIDfont.GetFontSpan();
Nicolas Penaf45ade32017-05-03 10:23:49 -04003057
3058 // Load the data into a FPDF_Font.
Tom Sepez20c41a52018-08-29 23:53:53 +00003059 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
3060 FPDF_FONT_TRUETYPE, 1));
Nicolas Penaf45ade32017-05-03 10:23:49 -04003061 ASSERT_TRUE(font.get());
3062
3063 // Add some text to the page
3064 FPDF_PAGEOBJECT text_object =
3065 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
3066 ASSERT_TRUE(text_object);
3067 std::wstring wstr = L"ABCDEFGhijklmnop.";
Lei Zhangf0f67682019-04-08 17:03:21 +00003068 ScopedFPDFWideString text = GetFPDFWideString(wstr);
Nicolas Penaf45ade32017-05-03 10:23:49 -04003069 EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
3070 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 200, 200);
3071 FPDFPage_InsertObject(page, text_object);
3072
3073 // And add some Japanese characters
3074 FPDF_PAGEOBJECT text_object2 =
3075 FPDFPageObj_CreateTextObj(document(), font.get(), 18.0f);
3076 ASSERT_TRUE(text_object2);
3077 std::wstring wstr2 =
3078 L"\u3053\u3093\u306B\u3061\u306f\u4e16\u754C\u3002\u3053\u3053\u306B1"
3079 L"\u756A";
Lei Zhangf0f67682019-04-08 17:03:21 +00003080 ScopedFPDFWideString text2 = GetFPDFWideString(wstr2);
Nicolas Penaf45ade32017-05-03 10:23:49 -04003081 EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
3082 FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 100, 500);
3083 FPDFPage_InsertObject(page, text_object2);
3084 }
3085
Nicolas Pena207b7272017-05-26 17:37:06 -04003086 // Check that the text renders properly.
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00003087#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
Tom Andersond4fe5f72021-12-03 20:52:52 +00003088 static constexpr char md5[] = "2e174d17de96a760d42ca3a06acbf36a";
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00003089#else
Tom Andersond4fe5f72021-12-03 20:52:52 +00003090 static constexpr char md5[] = "84d31d11b76845423a2cfc1879c0fbb9";
Hui Yingst5ce6a3f2020-11-11 02:29:09 +00003091#endif
Lei Zhang107fa7b2018-02-09 21:48:15 +00003092 {
Lei Zhang30ff2532019-01-31 21:37:55 +00003093 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Lei Zhang107fa7b2018-02-09 21:48:15 +00003094 CompareBitmap(page_bitmap.get(), 612, 792, md5);
3095 }
Nicolas Penaf45ade32017-05-03 10:23:49 -04003096
3097 // Save the document, close the page.
Nicolas Pena207b7272017-05-26 17:37:06 -04003098 EXPECT_TRUE(FPDFPage_GenerateContent(page));
Nicolas Penaf45ade32017-05-03 10:23:49 -04003099 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3100 FPDF_ClosePage(page);
Dan Sinclair04e4dc82017-10-18 12:17:14 -04003101
3102 VerifySavedDocument(612, 792, md5);
Nicolas Penaf45ade32017-05-03 10:23:49 -04003103}
Lei Zhangeb2da2a2022-01-12 19:28:33 +00003104#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003105
Hui Yingst29d377b2021-03-03 20:22:41 +00003106// TODO(crbug.com/pdfium/1651): Fix this issue and enable the test for Skia.
3107#if defined(_SKIA_SUPPORT_)
Lei Zhang03e5e682019-09-16 19:45:55 +00003108#define MAYBE_SaveAndRender DISABLED_SaveAndRender
3109#else
3110#define MAYBE_SaveAndRender SaveAndRender
3111#endif
3112TEST_F(FPDFEditEmbedderTest, MAYBE_SaveAndRender) {
Hui Yingst29d377b2021-03-03 20:22:41 +00003113#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
3114 static constexpr char kChecksum[] = "0e8b079e349e34f64211c495845a3529";
3115#else
3116 static constexpr char kChecksum[] = "3c20472b0552c0c22b88ab1ed8c6202b";
3117#endif
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003118 {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003119 ASSERT_TRUE(OpenDocument("bug_779.pdf"));
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003120 FPDF_PAGE page = LoadPage(0);
3121 ASSERT_NE(nullptr, page);
3122
Hui Yingst29d377b2021-03-03 20:22:41 +00003123 // Now add a more complex green path.
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003124 FPDF_PAGEOBJECT green_path = FPDFPageObj_CreateNewPath(20, 20);
Lei Zhang3475b482019-05-13 18:30:57 +00003125 EXPECT_TRUE(FPDFPageObj_SetFillColor(green_path, 0, 255, 0, 200));
Hui Yingst29d377b2021-03-03 20:22:41 +00003126 // TODO(npm): stroking will cause the checksums to differ.
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003127 EXPECT_TRUE(FPDFPath_SetDrawMode(green_path, FPDF_FILLMODE_WINDING, 0));
3128 EXPECT_TRUE(FPDFPath_LineTo(green_path, 20, 63));
3129 EXPECT_TRUE(FPDFPath_BezierTo(green_path, 55, 55, 78, 78, 90, 90));
3130 EXPECT_TRUE(FPDFPath_LineTo(green_path, 133, 133));
3131 EXPECT_TRUE(FPDFPath_LineTo(green_path, 133, 33));
3132 EXPECT_TRUE(FPDFPath_BezierTo(green_path, 38, 33, 39, 36, 40, 40));
3133 EXPECT_TRUE(FPDFPath_Close(green_path));
3134 FPDFPage_InsertObject(page, green_path);
Tom Sepeze08d2b12018-04-25 18:49:32 +00003135 ScopedFPDFBitmap page_bitmap = RenderLoadedPage(page);
Hui Yingst29d377b2021-03-03 20:22:41 +00003136 CompareBitmap(page_bitmap.get(), 612, 792, kChecksum);
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003137
3138 // Now save the result, closing the page and document
3139 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3140 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3141 UnloadPage(page);
3142 }
Dan Sinclair04e4dc82017-10-18 12:17:14 -04003143
Hui Yingst29d377b2021-03-03 20:22:41 +00003144 VerifySavedDocument(612, 792, kChecksum);
Nicolas Pena9ba8fbc2017-06-28 15:31:56 -04003145}
Jane Liu28fb7ba2017-08-02 21:45:57 -04003146
Lei Zhangab41f252018-12-23 03:10:50 +00003147TEST_F(FPDFEditEmbedderTest, AddMark) {
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003148 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003149 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003150 FPDF_PAGE page = LoadPage(0);
3151 ASSERT_TRUE(page);
3152
Lei Zhang2697cb12019-07-03 18:14:29 +00003153 CheckMarkCounts(page, 1, 19, 8, 4, 9, 1);
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003154
3155 // Add to the first page object a "Bounds" mark with "Position": "First".
3156 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
3157 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_AddMark(page_object, "Bounds");
3158 EXPECT_TRUE(mark);
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003159 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), page_object, mark,
3160 "Position", "First"));
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003161
Lei Zhang2697cb12019-07-03 18:14:29 +00003162 CheckMarkCounts(page, 1, 19, 8, 4, 9, 2);
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003163
3164 // Save the file
3165 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3166 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3167 UnloadPage(page);
3168
3169 // Re-open the file and check the new mark is present.
Lei Zhang0b494052019-01-31 21:41:15 +00003170 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003171 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00003172 ASSERT_TRUE(saved_page);
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003173
Lei Zhang2697cb12019-07-03 18:14:29 +00003174 CheckMarkCounts(saved_page, 1, 19, 8, 4, 9, 2);
3175
3176 CloseSavedPage(saved_page);
3177 CloseSavedDocument();
3178}
3179
Hui Yingst04440af2020-07-27 22:39:02 +00003180TEST_F(FPDFEditEmbedderTest, AddMarkCompressedStream) {
Lei Zhang2697cb12019-07-03 18:14:29 +00003181 // Load document with some text in a compressed stream.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003182 ASSERT_TRUE(OpenDocument("hello_world_compressed_stream.pdf"));
Lei Zhang2697cb12019-07-03 18:14:29 +00003183 FPDF_PAGE page = LoadPage(0);
3184 ASSERT_TRUE(page);
3185
3186 // Render and check there are no marks.
3187 {
3188 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00003189 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Lei Zhang2697cb12019-07-03 18:14:29 +00003190 }
3191 CheckMarkCounts(page, 0, 2, 0, 0, 0, 0);
3192
3193 // Add to the first page object a "Bounds" mark with "Position": "First".
3194 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
3195 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_AddMark(page_object, "Bounds");
3196 EXPECT_TRUE(mark);
3197 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), page_object, mark,
3198 "Position", "First"));
3199
3200 // Render and check there is 1 mark.
3201 {
3202 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00003203 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Lei Zhang2697cb12019-07-03 18:14:29 +00003204 }
3205 CheckMarkCounts(page, 0, 2, 0, 0, 0, 1);
3206
3207 // Save the file.
3208 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3209 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3210 UnloadPage(page);
3211
3212 // Re-open the file and check the new mark is present.
3213 ASSERT_TRUE(OpenSavedDocument());
3214 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00003215 ASSERT_TRUE(saved_page);
Lei Zhang2697cb12019-07-03 18:14:29 +00003216
3217 {
3218 ScopedFPDFBitmap page_bitmap = RenderPage(saved_page);
Hui Yingstb4baceb2020-04-28 23:46:10 +00003219 CompareBitmap(page_bitmap.get(), 200, 200, kHelloWorldChecksum);
Lei Zhang2697cb12019-07-03 18:14:29 +00003220 }
3221 CheckMarkCounts(saved_page, 0, 2, 0, 0, 0, 1);
Henrique Nakashimad8df8c32018-07-12 22:15:09 +00003222
3223 CloseSavedPage(saved_page);
3224 CloseSavedDocument();
3225}
3226
Lei Zhangab41f252018-12-23 03:10:50 +00003227TEST_F(FPDFEditEmbedderTest, SetMarkParam) {
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003228 // Load document with some text.
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003229 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003230 FPDF_PAGE page = LoadPage(0);
3231 ASSERT_TRUE(page);
3232
3233 constexpr int kExpectedObjectCount = 19;
3234 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
3235
3236 // Check the "Bounds" mark's "Position" param is "Last".
3237 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
3238 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
3239 ASSERT_TRUE(mark);
3240 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003241 unsigned long name_len = 999u;
3242 ASSERT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
3243 EXPECT_EQ((6u + 1u) * 2u, name_len);
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003244 ASSERT_EQ(L"Bounds",
3245 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3246 unsigned long out_buffer_len;
3247 ASSERT_TRUE(FPDFPageObjMark_GetParamStringValue(
3248 mark, "Position", buffer, sizeof(buffer), &out_buffer_len));
3249 ASSERT_EQ(L"Last",
3250 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3251
3252 // Set is to "End".
3253 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), page_object, mark,
3254 "Position", "End"));
3255
3256 // Verify the object passed must correspond to the mark passed.
3257 FPDF_PAGEOBJECT another_page_object = FPDFPage_GetObject(page, 17);
3258 EXPECT_FALSE(FPDFPageObjMark_SetStringParam(document(), another_page_object,
3259 mark, "Position", "End"));
3260
3261 // Verify nothing else changed.
3262 CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1);
3263
3264 // Verify "Position" now maps to "End".
3265 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
3266 mark, "Position", buffer, sizeof(buffer), &out_buffer_len));
3267 EXPECT_EQ(L"End",
3268 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3269
3270 // Save the file
3271 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3272 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3273 UnloadPage(page);
3274
3275 // Re-open the file and cerify "Position" still maps to "End".
Lei Zhang0b494052019-01-31 21:41:15 +00003276 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003277 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00003278 ASSERT_TRUE(saved_page);
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003279
3280 CheckMarkCounts(saved_page, 1, kExpectedObjectCount, 8, 4, 9, 1);
3281 page_object = FPDFPage_GetObject(saved_page, 18);
3282 mark = FPDFPageObj_GetMark(page_object, 1);
3283 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
3284 mark, "Position", buffer, sizeof(buffer), &out_buffer_len));
3285 EXPECT_EQ(L"End",
3286 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3287
3288 CloseSavedPage(saved_page);
3289 CloseSavedDocument();
3290}
3291
Hui Yingst9d6ec8f2020-11-05 23:35:38 +00003292TEST_F(FPDFEditEmbedderTest, AddMarkedText) {
Henrique Nakashima144107d2018-07-10 21:04:05 +00003293 // Start with a blank page.
3294 FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
3295
Tom Sepezffff6c52019-07-30 21:56:19 +00003296 RetainPtr<CPDF_Font> stock_font =
3297 CPDF_Font::GetStockFont(cpdf_doc(), "Arial");
Tom Sepez20c41a52018-08-29 23:53:53 +00003298 pdfium::span<const uint8_t> span = stock_font->GetFont()->GetFontSpan();
3299 ScopedFPDFFont font(FPDFText_LoadFont(document(), span.data(), span.size(),
3300 FPDF_FONT_TRUETYPE, 0));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003301 ASSERT_TRUE(font.get());
3302
3303 // Add some text to the page.
3304 FPDF_PAGEOBJECT text_object =
3305 FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
3306
3307 EXPECT_TRUE(text_object);
Hui Yingst3b6136a2020-06-09 00:39:33 +00003308 ScopedFPDFWideString text1 = GetFPDFWideString(kLoadedFontText);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003309 EXPECT_TRUE(FPDFText_SetText(text_object, text1.get()));
3310 FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 400, 400);
3311 FPDFPage_InsertObject(page, text_object);
3312
3313 // Add a mark with the tag "TestMarkName" to that text.
3314 EXPECT_EQ(0, FPDFPageObj_CountMarks(text_object));
Henrique Nakashima6fc8d872018-09-18 16:48:31 +00003315 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_AddMark(text_object, "Test Mark Name");
Henrique Nakashima144107d2018-07-10 21:04:05 +00003316 EXPECT_TRUE(mark);
3317 EXPECT_EQ(1, FPDFPageObj_CountMarks(text_object));
3318 EXPECT_EQ(mark, FPDFPageObj_GetMark(text_object, 0));
3319 char buffer[256];
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003320 unsigned long name_len = 999u;
3321 ASSERT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
3322 EXPECT_EQ((14u + 1u) * 2, name_len);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003323 std::wstring name =
3324 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
Henrique Nakashima6fc8d872018-09-18 16:48:31 +00003325 EXPECT_EQ(L"Test Mark Name", name);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003326
3327 // Add parameters:
3328 // - int "IntKey" : 42
3329 // - string "StringKey": "StringValue"
Henrique Nakashima07520f62018-07-12 19:45:29 +00003330 // - blob "BlobKey": "\x01\x02\x03\0BlobValue1\0\0\0BlobValue2\0"
Lei Zhang590f4242019-05-15 20:57:26 +00003331 constexpr size_t kBlobLen = 28;
Lei Zhangd3b028b2018-11-30 22:22:00 +00003332 char block_value[kBlobLen];
3333 memcpy(block_value, "\x01\x02\x03\0BlobValue1\0\0\0BlobValue2\0", kBlobLen);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003334 EXPECT_EQ(0, FPDFPageObjMark_CountParams(mark));
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003335 EXPECT_TRUE(
3336 FPDFPageObjMark_SetIntParam(document(), text_object, mark, "IntKey", 42));
3337 EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), text_object, mark,
3338 "StringKey", "StringValue"));
3339 EXPECT_TRUE(FPDFPageObjMark_SetBlobParam(document(), text_object, mark,
Lei Zhangd3b028b2018-11-30 22:22:00 +00003340 "BlobKey", block_value, kBlobLen));
Henrique Nakashima07520f62018-07-12 19:45:29 +00003341 EXPECT_EQ(3, FPDFPageObjMark_CountParams(mark));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003342
3343 // Check the two parameters can be retrieved.
3344 EXPECT_EQ(FPDF_OBJECT_NUMBER,
Henrique Nakashima94230e52018-07-11 22:02:02 +00003345 FPDFPageObjMark_GetParamValueType(mark, "IntKey"));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003346 int int_value;
Henrique Nakashima94230e52018-07-11 22:02:02 +00003347 EXPECT_TRUE(FPDFPageObjMark_GetParamIntValue(mark, "IntKey", &int_value));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003348 EXPECT_EQ(42, int_value);
3349
3350 EXPECT_EQ(FPDF_OBJECT_STRING,
Henrique Nakashima94230e52018-07-11 22:02:02 +00003351 FPDFPageObjMark_GetParamValueType(mark, "StringKey"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003352 unsigned long out_buffer_len = 999u;
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003353 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
3354 mark, "StringKey", buffer, sizeof(buffer), &out_buffer_len));
Henrique Nakashima144107d2018-07-10 21:04:05 +00003355 EXPECT_GT(out_buffer_len, 0u);
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003356 EXPECT_NE(999u, out_buffer_len);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003357 name = GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
3358 EXPECT_EQ(L"StringValue", name);
3359
Henrique Nakashima07520f62018-07-12 19:45:29 +00003360 EXPECT_EQ(FPDF_OBJECT_STRING,
3361 FPDFPageObjMark_GetParamValueType(mark, "BlobKey"));
3362 out_buffer_len = 0;
Henrique Nakashimaa3406772018-07-13 19:10:53 +00003363 EXPECT_TRUE(FPDFPageObjMark_GetParamBlobValue(
3364 mark, "BlobKey", buffer, sizeof(buffer), &out_buffer_len));
Henrique Nakashima07520f62018-07-12 19:45:29 +00003365 EXPECT_EQ(kBlobLen, out_buffer_len);
Lei Zhangd3b028b2018-11-30 22:22:00 +00003366 EXPECT_EQ(0, memcmp(block_value, buffer, kBlobLen));
Henrique Nakashima07520f62018-07-12 19:45:29 +00003367
Lei Zhangf16376e2020-06-18 19:19:32 +00003368 // Render and check the bitmap is the expected one.
Henrique Nakashima144107d2018-07-10 21:04:05 +00003369 {
Lei Zhang30ff2532019-01-31 21:37:55 +00003370 ScopedFPDFBitmap page_bitmap = RenderPage(page);
Hui Yingst3b6136a2020-06-09 00:39:33 +00003371 CompareBitmap(page_bitmap.get(), 612, 792, kLoadedFontTextChecksum);
Henrique Nakashima144107d2018-07-10 21:04:05 +00003372 }
3373
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003374 // Now save the result.
3375 EXPECT_EQ(1, FPDFPage_CountObjects(page));
3376 EXPECT_TRUE(FPDFPage_GenerateContent(page));
3377 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
3378
Henrique Nakashima144107d2018-07-10 21:04:05 +00003379 FPDF_ClosePage(page);
3380
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003381 // Re-open the file and check the changes were kept in the saved .pdf.
Lei Zhang0b494052019-01-31 21:41:15 +00003382 ASSERT_TRUE(OpenSavedDocument());
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003383 FPDF_PAGE saved_page = LoadSavedPage(0);
Lei Zhangec618142021-04-13 17:36:46 +00003384 ASSERT_TRUE(saved_page);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003385 EXPECT_EQ(1, FPDFPage_CountObjects(saved_page));
3386
3387 text_object = FPDFPage_GetObject(saved_page, 0);
3388 EXPECT_TRUE(text_object);
3389 EXPECT_EQ(1, FPDFPageObj_CountMarks(text_object));
3390 mark = FPDFPageObj_GetMark(text_object, 0);
3391 EXPECT_TRUE(mark);
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003392
3393 name_len = 999u;
3394 ASSERT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
3395 EXPECT_EQ((14u + 1u) * 2, name_len);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003396 name = GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
Henrique Nakashima6fc8d872018-09-18 16:48:31 +00003397 EXPECT_EQ(L"Test Mark Name", name);
Henrique Nakashimab4bcf692018-07-11 21:19:22 +00003398
3399 CloseSavedPage(saved_page);
3400 CloseSavedDocument();
Henrique Nakashima144107d2018-07-10 21:04:05 +00003401}
3402
Lei Zhangab41f252018-12-23 03:10:50 +00003403TEST_F(FPDFEditEmbedderTest, MarkGetName) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003404 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003405 FPDF_PAGE page = LoadPage(0);
3406 ASSERT_TRUE(page);
3407 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
3408 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
3409 ASSERT_TRUE(mark);
3410
3411 char buffer[256];
3412 unsigned long out_len;
3413
3414 // Show the positive cases of FPDFPageObjMark_GetName.
3415 out_len = 999u;
3416 EXPECT_TRUE(FPDFPageObjMark_GetName(mark, nullptr, 0, &out_len));
3417 EXPECT_EQ((6u + 1u) * 2u, out_len);
3418
3419 out_len = 999u;
3420 EXPECT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &out_len));
3421 EXPECT_EQ(L"Bounds",
3422 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3423 EXPECT_EQ((6u + 1u) * 2u, out_len);
3424
3425 // Show the negative cases of FPDFPageObjMark_GetName.
3426 out_len = 999u;
3427 EXPECT_FALSE(
3428 FPDFPageObjMark_GetName(nullptr, buffer, sizeof(buffer), &out_len));
3429 EXPECT_EQ(999u, out_len);
3430
3431 EXPECT_FALSE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), nullptr));
3432
3433 UnloadPage(page);
3434}
3435
Lei Zhangab41f252018-12-23 03:10:50 +00003436TEST_F(FPDFEditEmbedderTest, MarkGetParamKey) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003437 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003438 FPDF_PAGE page = LoadPage(0);
3439 ASSERT_TRUE(page);
3440 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
3441 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
3442 ASSERT_TRUE(mark);
3443
3444 char buffer[256];
3445 unsigned long out_len;
3446
3447 // Show the positive cases of FPDFPageObjMark_GetParamKey.
3448 out_len = 999u;
3449 EXPECT_TRUE(FPDFPageObjMark_GetParamKey(mark, 0, nullptr, 0, &out_len));
3450 EXPECT_EQ((8u + 1u) * 2u, out_len);
3451
3452 out_len = 999u;
3453 EXPECT_TRUE(
3454 FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer), &out_len));
3455 EXPECT_EQ(L"Position",
3456 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3457 EXPECT_EQ((8u + 1u) * 2u, out_len);
3458
3459 // Show the negative cases of FPDFPageObjMark_GetParamKey.
3460 out_len = 999u;
3461 EXPECT_FALSE(FPDFPageObjMark_GetParamKey(nullptr, 0, buffer, sizeof(buffer),
3462 &out_len));
3463 EXPECT_EQ(999u, out_len);
3464
3465 out_len = 999u;
3466 EXPECT_FALSE(
3467 FPDFPageObjMark_GetParamKey(mark, 1, buffer, sizeof(buffer), &out_len));
3468 EXPECT_EQ(999u, out_len);
3469
3470 EXPECT_FALSE(
3471 FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer), nullptr));
3472
3473 UnloadPage(page);
3474}
3475
Lei Zhangab41f252018-12-23 03:10:50 +00003476TEST_F(FPDFEditEmbedderTest, MarkGetIntParam) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003477 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003478 FPDF_PAGE page = LoadPage(0);
3479 ASSERT_TRUE(page);
3480 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 8);
3481 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 0);
3482 ASSERT_TRUE(mark);
3483
3484 int out_value;
3485
3486 // Show the positive cases of FPDFPageObjMark_GetParamIntValue.
3487 out_value = 999;
3488 EXPECT_TRUE(FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
3489 EXPECT_EQ(3, out_value);
3490
3491 // Show the negative cases of FPDFPageObjMark_GetParamIntValue.
3492 out_value = 999;
3493 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(nullptr, "Factor", &out_value));
3494 EXPECT_EQ(999, out_value);
3495
3496 out_value = 999;
3497 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(mark, "ParamThatDoesNotExist",
3498 &out_value));
3499 EXPECT_EQ(999, out_value);
3500
3501 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(mark, "Factor", nullptr));
3502
3503 page_object = FPDFPage_GetObject(page, 18);
3504 mark = FPDFPageObj_GetMark(page_object, 1);
3505 out_value = 999;
3506 EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(mark, "Position", &out_value));
3507 EXPECT_EQ(999, out_value);
3508
3509 UnloadPage(page);
3510}
3511
Lei Zhangab41f252018-12-23 03:10:50 +00003512TEST_F(FPDFEditEmbedderTest, MarkGetStringParam) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003513 ASSERT_TRUE(OpenDocument("text_in_page_marked.pdf"));
Henrique Nakashimac3099d12018-09-18 18:08:15 +00003514 FPDF_PAGE page = LoadPage(0);
3515 ASSERT_TRUE(page);
3516 FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
3517 FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
3518 ASSERT_TRUE(mark);
3519
3520 char buffer[256];
3521 unsigned long out_len;
3522
3523 // Show the positive cases of FPDFPageObjMark_GetParamStringValue.
3524 out_len = 999u;
3525 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(mark, "Position", nullptr, 0,
3526 &out_len));
3527 EXPECT_EQ((4u + 1u) * 2u, out_len);
3528
3529 out_len = 999u;
3530 EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(mark, "Position", buffer,
3531 sizeof(buffer), &out_len));
3532 EXPECT_EQ(L"Last",
3533 GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
3534 EXPECT_EQ((4u + 1u) * 2u, out_len);
3535
3536 // Show the negative cases of FPDFPageObjMark_GetParamStringValue.
3537 out_len = 999u;
3538 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(nullptr, "Position", buffer,
3539 sizeof(buffer), &out_len));
3540 EXPECT_EQ(999u, out_len);
3541
3542 out_len = 999u;
3543 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(
3544 mark, "ParamThatDoesNotExist", buffer, sizeof(buffer), &out_len));
3545 EXPECT_EQ(999u, out_len);
3546
3547 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(mark, "Position", buffer,
3548 sizeof(buffer), nullptr));
3549
3550 page_object = FPDFPage_GetObject(page, 8);
3551 mark = FPDFPageObj_GetMark(page_object, 0);
3552 out_len = 999u;
3553 EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(mark, "Factor", buffer,
3554 sizeof(buffer), &out_len));
3555 EXPECT_EQ(999u, out_len);
3556
3557 UnloadPage(page);
3558}
3559
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003560TEST_F(FPDFEditEmbedderTest, GetBitmap) {
Jane Liu28fb7ba2017-08-02 21:45:57 -04003561 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3562 FPDF_PAGE page = LoadPage(0);
3563 ASSERT_TRUE(page);
Miklos Vajna92627612017-09-25 12:59:29 +02003564 ASSERT_EQ(39, FPDFPage_CountObjects(page));
Jane Liu28fb7ba2017-08-02 21:45:57 -04003565
3566 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 32);
3567 EXPECT_NE(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3568 EXPECT_FALSE(FPDFImageObj_GetBitmap(obj));
3569
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003570 {
3571 obj = FPDFPage_GetObject(page, 33);
3572 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3573 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3574 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
Lei Zhang85166512020-07-14 23:28:56 +00003575 CompareBitmap(bitmap.get(), 109, 88, kEmbeddedImage33Checksum);
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003576 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003577
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003578 {
3579 obj = FPDFPage_GetObject(page, 34);
3580 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3581 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3582 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3583 CompareBitmap(bitmap.get(), 103, 75, "c8d51fa6821ceb2a67f08446ff236c40");
3584 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003585
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003586 {
3587 obj = FPDFPage_GetObject(page, 35);
3588 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3589 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3590 EXPECT_EQ(FPDFBitmap_Gray, FPDFBitmap_GetFormat(bitmap.get()));
3591 CompareBitmap(bitmap.get(), 92, 68, "9c6d76cb1e37ef8514f9455d759391f3");
3592 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003593
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003594 {
3595 obj = FPDFPage_GetObject(page, 36);
3596 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3597 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3598 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3599 CompareBitmap(bitmap.get(), 79, 60, "f4e72fb783a01c7b4614cdc25eaa98ac");
3600 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003601
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003602 {
3603 obj = FPDFPage_GetObject(page, 37);
3604 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3605 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3606 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3607 CompareBitmap(bitmap.get(), 126, 106, "2cf9e66414c72461f4ccbf9cdebdfa1b");
3608 }
Jane Liu28fb7ba2017-08-02 21:45:57 -04003609
Lei Zhang89ebf5c2020-07-14 20:59:05 +00003610 {
3611 obj = FPDFPage_GetObject(page, 38);
3612 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3613 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3614 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3615 CompareBitmap(bitmap.get(), 194, 119, "a8f3a126cec274dab8242fd2ccdc1b8b");
3616 }
3617
Jane Liu28fb7ba2017-08-02 21:45:57 -04003618 UnloadPage(page);
3619}
Jane Liu548334e2017-08-03 16:33:40 -04003620
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003621TEST_F(FPDFEditEmbedderTest, GetBitmapIgnoresSetMatrix) {
Lei Zhang85166512020-07-14 23:28:56 +00003622 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3623 FPDF_PAGE page = LoadPage(0);
3624 ASSERT_TRUE(page);
3625 ASSERT_EQ(39, FPDFPage_CountObjects(page));
3626
3627 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3628 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3629
3630 {
3631 // Render |obj| as is.
3632 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3633 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3634 CompareBitmap(bitmap.get(), 109, 88, kEmbeddedImage33Checksum);
3635 }
3636
3637 // Check the matrix for |obj|.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003638 FS_MATRIX matrix;
3639 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3640 EXPECT_FLOAT_EQ(53.0f, matrix.a);
3641 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3642 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3643 EXPECT_FLOAT_EQ(43.0f, matrix.d);
3644 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3645 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang85166512020-07-14 23:28:56 +00003646
3647 // Modify the matrix for |obj|.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003648 matrix.a = 120.0;
3649 EXPECT_TRUE(FPDFPageObj_SetMatrix(obj, &matrix));
Lei Zhang85166512020-07-14 23:28:56 +00003650
3651 // Make sure the matrix modification took place.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003652 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3653 EXPECT_FLOAT_EQ(120.0f, matrix.a);
3654 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3655 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3656 EXPECT_FLOAT_EQ(43.0f, matrix.d);
3657 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3658 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang85166512020-07-14 23:28:56 +00003659
3660 {
Lei Zhangc8601bf2021-06-29 23:19:27 +00003661 // Render |obj| again. Note that the FPDFPageObj_SetMatrix() call has no
Lei Zhang85166512020-07-14 23:28:56 +00003662 // effect.
3663 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3664 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3665 CompareBitmap(bitmap.get(), 109, 88, kEmbeddedImage33Checksum);
3666 }
3667
3668 UnloadPage(page);
3669}
3670
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003671TEST_F(FPDFEditEmbedderTest, GetBitmapForJBigImage) {
Lei Zhang53341dd2018-03-01 15:42:47 +00003672 ASSERT_TRUE(OpenDocument("bug_631912.pdf"));
3673 FPDF_PAGE page = LoadPage(0);
3674 ASSERT_TRUE(page);
3675 ASSERT_EQ(1, FPDFPage_CountObjects(page));
3676
3677 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
3678 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3679 {
Tom Sepeze08d2b12018-04-25 18:49:32 +00003680 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
Lei Zhang1330ebb2018-03-05 15:16:37 +00003681 ASSERT_TRUE(bitmap);
3682 EXPECT_EQ(FPDFBitmap_Gray, FPDFBitmap_GetFormat(bitmap.get()));
3683 CompareBitmap(bitmap.get(), 1152, 720, "3f6a48e2b3e91b799bf34567f55cb4de");
Lei Zhang53341dd2018-03-01 15:42:47 +00003684 }
3685
3686 UnloadPage(page);
3687}
3688
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003689TEST_F(FPDFEditEmbedderTest, GetBitmapIgnoresSMask) {
Lei Zhang2e1b4f22020-07-08 23:40:18 +00003690 ASSERT_TRUE(OpenDocument("matte.pdf"));
3691 FPDF_PAGE page = LoadPage(0);
3692 ASSERT_TRUE(page);
3693
3694 constexpr int kExpectedObjects = 4;
3695 ASSERT_EQ(kExpectedObjects, FPDFPage_CountObjects(page));
3696
3697 for (int i = 0; i < kExpectedObjects; ++i) {
3698 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, i);
3699 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3700 ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(obj));
3701 ASSERT_TRUE(bitmap);
3702 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
3703 CompareBitmap(bitmap.get(), 50, 50, "46c9a1dbe0b44765ce46017ad629a2fe");
3704 }
3705
3706 UnloadPage(page);
3707}
3708
Hui Yingst822fb8d2020-10-05 22:10:35 +00003709// TODO(crbug.com/pdfium/11): Fix this test and enable.
3710#if defined(_SKIA_SUPPORT_)
3711#define MAYBE_GetRenderedBitmapHandlesSetMatrix \
3712 DISABLED_GetRenderedBitmapHandlesSetMatrix
3713#else
3714#define MAYBE_GetRenderedBitmapHandlesSetMatrix \
3715 GetRenderedBitmapHandlesSetMatrix
3716#endif
3717TEST_F(FPDFEditEmbedderTest, MAYBE_GetRenderedBitmapHandlesSetMatrix) {
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003718 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3719 FPDF_PAGE page = LoadPage(0);
3720 ASSERT_TRUE(page);
3721 ASSERT_EQ(39, FPDFPage_CountObjects(page));
3722
3723 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3724 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3725
3726 {
3727 // Render |obj| as is.
3728 ScopedFPDFBitmap bitmap(
3729 FPDFImageObj_GetRenderedBitmap(document(), page, obj));
3730 EXPECT_EQ(FPDFBitmap_BGRA, FPDFBitmap_GetFormat(bitmap.get()));
Tom Sepezd661dc72021-06-24 20:22:19 +00003731 CompareBitmap(bitmap.get(), 53, 43, "582ca300e003f512d7b552c7b5b45d2e");
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003732 }
3733
3734 // Check the matrix for |obj|.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003735 FS_MATRIX matrix;
3736 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3737 EXPECT_FLOAT_EQ(53.0f, matrix.a);
3738 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3739 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3740 EXPECT_FLOAT_EQ(43.0f, matrix.d);
3741 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3742 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003743
3744 // Modify the matrix for |obj|.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003745 matrix.a = 120.0;
3746 EXPECT_TRUE(FPDFPageObj_SetMatrix(obj, &matrix));
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003747
3748 // Make sure the matrix modification took place.
Lei Zhangc8601bf2021-06-29 23:19:27 +00003749 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3750 EXPECT_FLOAT_EQ(120.0f, matrix.a);
3751 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3752 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3753 EXPECT_FLOAT_EQ(43.0f, matrix.d);
3754 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3755 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003756
3757 {
Lei Zhangc8601bf2021-06-29 23:19:27 +00003758 // Render |obj| again. Note that the FPDFPageObj_SetMatrix() call has an
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003759 // effect.
3760 ScopedFPDFBitmap bitmap(
3761 FPDFImageObj_GetRenderedBitmap(document(), page, obj));
3762 EXPECT_EQ(FPDFBitmap_BGRA, FPDFBitmap_GetFormat(bitmap.get()));
Tom Sepezd661dc72021-06-24 20:22:19 +00003763 CompareBitmap(bitmap.get(), 120, 43, "0824c16dcf2dfcef44b45d88db1fddce");
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003764 }
3765
3766 UnloadPage(page);
3767}
3768
Hui Yingst822fb8d2020-10-05 22:10:35 +00003769// TODO(crbug.com/pdfium/11): Fix this test and enable.
3770#if defined(_SKIA_SUPPORT_)
3771#define MAYBE_GetRenderedBitmapHandlesSMask \
3772 DISABLED_GetRenderedBitmapHandlesSMask
3773#else
3774#define MAYBE_GetRenderedBitmapHandlesSMask GetRenderedBitmapHandlesSMask
3775#endif
3776TEST_F(FPDFEditEmbedderTest, MAYBE_GetRenderedBitmapHandlesSMask) {
Lei Zhang0ac7b4e2020-07-18 00:35:53 +00003777 ASSERT_TRUE(OpenDocument("matte.pdf"));
3778 FPDF_PAGE page = LoadPage(0);
3779 ASSERT_TRUE(page);
3780
3781 constexpr int kExpectedObjects = 4;
3782 ASSERT_EQ(kExpectedObjects, FPDFPage_CountObjects(page));
3783
3784 for (int i = 0; i < kExpectedObjects; ++i) {
3785 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, i);
3786 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3787 ScopedFPDFBitmap bitmap(
3788 FPDFImageObj_GetRenderedBitmap(document(), page, obj));
3789 ASSERT_TRUE(bitmap);
3790 EXPECT_EQ(FPDFBitmap_BGRA, FPDFBitmap_GetFormat(bitmap.get()));
3791 if (i == 0)
3792 CompareBitmap(bitmap.get(), 40, 60, "5a3ae4a660ce919e29c42ec2258142f1");
3793 else
3794 CompareBitmap(bitmap.get(), 40, 60, "67504e83f5d78214ea00efc19082c5c1");
3795 }
3796
3797 UnloadPage(page);
3798}
3799
3800TEST_F(FPDFEditEmbedderTest, GetRenderedBitmapBadParams) {
3801 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3802 FPDF_PAGE page = LoadPage(0);
3803 ASSERT_TRUE(page);
3804
3805 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3806 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3807
3808 // Test various null parameters.
3809 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, nullptr, nullptr));
3810 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(document(), nullptr, nullptr));
3811 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, page, nullptr));
3812 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, nullptr, obj));
3813 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(document(), page, nullptr));
3814 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(nullptr, page, obj));
3815
3816 // Test mismatch between document and page parameters.
3817 ScopedFPDFDocument new_document(FPDF_CreateNewDocument());
3818 EXPECT_FALSE(FPDFImageObj_GetRenderedBitmap(new_document.get(), page, obj));
3819
3820 UnloadPage(page);
3821}
3822
Lei Zhangab41f252018-12-23 03:10:50 +00003823TEST_F(FPDFEditEmbedderTest, GetImageData) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003824 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
Jane Liu548334e2017-08-03 16:33:40 -04003825 FPDF_PAGE page = LoadPage(0);
3826 ASSERT_TRUE(page);
Miklos Vajna92627612017-09-25 12:59:29 +02003827 ASSERT_EQ(39, FPDFPage_CountObjects(page));
Jane Liu548334e2017-08-03 16:33:40 -04003828
3829 // Retrieve an image object with flate-encoded data stream.
3830 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
3831 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3832
3833 // Check that the raw image data has the correct length and hash value.
3834 unsigned long len = FPDFImageObj_GetImageDataRaw(obj, nullptr, 0);
3835 std::vector<char> buf(len);
3836 EXPECT_EQ(4091u, FPDFImageObj_GetImageDataRaw(obj, buf.data(), len));
3837 EXPECT_EQ("f73802327d2e88e890f653961bcda81a",
3838 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3839
3840 // Check that the decoded image data has the correct length and hash value.
3841 len = FPDFImageObj_GetImageDataDecoded(obj, nullptr, 0);
3842 buf.clear();
3843 buf.resize(len);
3844 EXPECT_EQ(28776u, FPDFImageObj_GetImageDataDecoded(obj, buf.data(), len));
Lei Zhang85166512020-07-14 23:28:56 +00003845 EXPECT_EQ(kEmbeddedImage33Checksum,
Jane Liu548334e2017-08-03 16:33:40 -04003846 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3847
Lei Zhang351e8b02018-12-20 01:10:06 +00003848 // Retrieve an image object with DCTDecode-encoded data stream.
Jane Liu548334e2017-08-03 16:33:40 -04003849 obj = FPDFPage_GetObject(page, 37);
3850 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3851
3852 // Check that the raw image data has the correct length and hash value.
3853 len = FPDFImageObj_GetImageDataRaw(obj, nullptr, 0);
3854 buf.clear();
3855 buf.resize(len);
3856 EXPECT_EQ(4370u, FPDFImageObj_GetImageDataRaw(obj, buf.data(), len));
3857 EXPECT_EQ("6aae1f3710335023a9e12191be66b64b",
3858 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3859
3860 // Check that the decoded image data has the correct length and hash value,
3861 // which should be the same as those of the raw data, since this image is
3862 // encoded by a single DCTDecode filter and decoding is a noop.
3863 len = FPDFImageObj_GetImageDataDecoded(obj, nullptr, 0);
3864 buf.clear();
3865 buf.resize(len);
3866 EXPECT_EQ(4370u, FPDFImageObj_GetImageDataDecoded(obj, buf.data(), len));
3867 EXPECT_EQ("6aae1f3710335023a9e12191be66b64b",
3868 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
3869
3870 UnloadPage(page);
3871}
Jane Liu2e5f0ae2017-08-08 15:23:27 -04003872
Lei Zhangab41f252018-12-23 03:10:50 +00003873TEST_F(FPDFEditEmbedderTest, GetImageMatrix) {
Lei Zhang866d6882018-10-24 17:31:01 +00003874 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
3875 FPDF_PAGE page = LoadPage(0);
3876 ASSERT_TRUE(page);
3877 ASSERT_EQ(39, FPDFPage_CountObjects(page));
3878
3879 FPDF_PAGEOBJECT obj;
Lei Zhangc8601bf2021-06-29 23:19:27 +00003880 FS_MATRIX matrix;
Lei Zhang866d6882018-10-24 17:31:01 +00003881
3882 obj = FPDFPage_GetObject(page, 33);
3883 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003884 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3885 EXPECT_FLOAT_EQ(53.0f, matrix.a);
3886 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3887 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3888 EXPECT_FLOAT_EQ(43.0f, matrix.d);
3889 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3890 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003891
3892 obj = FPDFPage_GetObject(page, 34);
3893 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003894 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3895 EXPECT_FLOAT_EQ(70.0f, matrix.a);
3896 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3897 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3898 EXPECT_FLOAT_EQ(51.0f, matrix.d);
3899 EXPECT_FLOAT_EQ(216.0f, matrix.e);
3900 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003901
3902 obj = FPDFPage_GetObject(page, 35);
3903 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003904 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3905 EXPECT_FLOAT_EQ(69.0f, matrix.a);
3906 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3907 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3908 EXPECT_FLOAT_EQ(51.0f, matrix.d);
3909 EXPECT_FLOAT_EQ(360.0f, matrix.e);
3910 EXPECT_FLOAT_EQ(646.510009765625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003911
3912 obj = FPDFPage_GetObject(page, 36);
3913 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003914 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3915 EXPECT_FLOAT_EQ(59.0f, matrix.a);
3916 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3917 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3918 EXPECT_FLOAT_EQ(45.0f, matrix.d);
3919 EXPECT_FLOAT_EQ(72.0f, matrix.e);
3920 EXPECT_FLOAT_EQ(553.510009765625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003921
3922 obj = FPDFPage_GetObject(page, 37);
3923 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003924 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3925 EXPECT_FLOAT_EQ(55.94000244140625f, matrix.a);
3926 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3927 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3928 EXPECT_FLOAT_EQ(46.950000762939453f, matrix.d);
3929 EXPECT_FLOAT_EQ(216.0f, matrix.e);
3930 EXPECT_FLOAT_EQ(552.510009765625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003931
3932 obj = FPDFPage_GetObject(page, 38);
3933 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
Lei Zhangc8601bf2021-06-29 23:19:27 +00003934 EXPECT_TRUE(FPDFPageObj_GetMatrix(obj, &matrix));
3935 EXPECT_FLOAT_EQ(70.528999328613281f, matrix.a);
3936 EXPECT_FLOAT_EQ(0.0f, matrix.b);
3937 EXPECT_FLOAT_EQ(0.0f, matrix.c);
3938 EXPECT_FLOAT_EQ(43.149997711181641f, matrix.d);
3939 EXPECT_FLOAT_EQ(360.0f, matrix.e);
3940 EXPECT_FLOAT_EQ(553.3599853515625f, matrix.f);
Lei Zhang866d6882018-10-24 17:31:01 +00003941
3942 UnloadPage(page);
3943}
3944
Lei Zhangab41f252018-12-23 03:10:50 +00003945TEST_F(FPDFEditEmbedderTest, DestroyPageObject) {
Jane Liu2e5f0ae2017-08-08 15:23:27 -04003946 FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
3947 ASSERT_TRUE(rect);
3948
3949 // There should be no memory leaks with a call to FPDFPageObj_Destroy().
3950 FPDFPageObj_Destroy(rect);
3951}
Jane Liube63ab92017-08-09 14:09:34 -04003952
Lei Zhangab41f252018-12-23 03:10:50 +00003953TEST_F(FPDFEditEmbedderTest, GetImageFilters) {
Daniel Hosseinian5af51b62020-07-18 00:53:43 +00003954 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
Jane Liube63ab92017-08-09 14:09:34 -04003955 FPDF_PAGE page = LoadPage(0);
3956 ASSERT_TRUE(page);
3957
3958 // Verify that retrieving the filter of a non-image object would fail.
3959 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 32);
3960 ASSERT_NE(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3961 ASSERT_EQ(0, FPDFImageObj_GetImageFilterCount(obj));
3962 EXPECT_EQ(0u, FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0));
3963
3964 // Verify the returned filter string for an image object with a single filter.
3965 obj = FPDFPage_GetObject(page, 33);
3966 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3967 ASSERT_EQ(1, FPDFImageObj_GetImageFilterCount(obj));
3968 unsigned long len = FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0);
3969 std::vector<char> buf(len);
Lei Zhang0733a1b2017-08-31 12:36:31 -07003970 static constexpr char kFlateDecode[] = "FlateDecode";
3971 EXPECT_EQ(sizeof(kFlateDecode),
3972 FPDFImageObj_GetImageFilter(obj, 0, buf.data(), len));
3973 EXPECT_STREQ(kFlateDecode, buf.data());
Jane Liube63ab92017-08-09 14:09:34 -04003974 EXPECT_EQ(0u, FPDFImageObj_GetImageFilter(obj, 1, nullptr, 0));
3975
3976 // Verify all the filters for an image object with a list of filters.
3977 obj = FPDFPage_GetObject(page, 38);
3978 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
3979 ASSERT_EQ(2, FPDFImageObj_GetImageFilterCount(obj));
3980 len = FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0);
3981 buf.clear();
3982 buf.resize(len);
Lei Zhang0733a1b2017-08-31 12:36:31 -07003983 static constexpr char kASCIIHexDecode[] = "ASCIIHexDecode";
3984 EXPECT_EQ(sizeof(kASCIIHexDecode),
3985 FPDFImageObj_GetImageFilter(obj, 0, buf.data(), len));
3986 EXPECT_STREQ(kASCIIHexDecode, buf.data());
Jane Liube63ab92017-08-09 14:09:34 -04003987
3988 len = FPDFImageObj_GetImageFilter(obj, 1, nullptr, 0);
3989 buf.clear();
3990 buf.resize(len);
Lei Zhang0733a1b2017-08-31 12:36:31 -07003991 static constexpr char kDCTDecode[] = "DCTDecode";
3992 EXPECT_EQ(sizeof(kDCTDecode),
3993 FPDFImageObj_GetImageFilter(obj, 1, buf.data(), len));
3994 EXPECT_STREQ(kDCTDecode, buf.data());
Jane Liube63ab92017-08-09 14:09:34 -04003995
3996 UnloadPage(page);
3997}
Jane Liuca898292017-08-16 11:25:35 -04003998
Lei Zhangab41f252018-12-23 03:10:50 +00003999TEST_F(FPDFEditEmbedderTest, GetImageMetadata) {
Jane Liuca898292017-08-16 11:25:35 -04004000 ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
4001 FPDF_PAGE page = LoadPage(0);
4002 ASSERT_TRUE(page);
4003
4004 // Check that getting the metadata of a null object would fail.
4005 FPDF_IMAGEOBJ_METADATA metadata;
4006 EXPECT_FALSE(FPDFImageObj_GetImageMetadata(nullptr, page, &metadata));
4007
4008 // Check that receiving the metadata with a null metadata object would fail.
4009 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 35);
4010 EXPECT_FALSE(FPDFImageObj_GetImageMetadata(obj, page, nullptr));
4011
4012 // Check that when retrieving an image object's metadata without passing in
4013 // |page|, all values are correct, with the last two being default values.
4014 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
4015 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, nullptr, &metadata));
Julian Lungerecd063e2017-12-27 10:18:50 -05004016 EXPECT_EQ(7, metadata.marked_content_id);
Jane Liuca898292017-08-16 11:25:35 -04004017 EXPECT_EQ(92u, metadata.width);
4018 EXPECT_EQ(68u, metadata.height);
Lei Zhang351e8b02018-12-20 01:10:06 +00004019 EXPECT_FLOAT_EQ(96.0f, metadata.horizontal_dpi);
4020 EXPECT_FLOAT_EQ(96.0f, metadata.vertical_dpi);
Jane Liuca898292017-08-16 11:25:35 -04004021 EXPECT_EQ(0u, metadata.bits_per_pixel);
4022 EXPECT_EQ(FPDF_COLORSPACE_UNKNOWN, metadata.colorspace);
4023
4024 // Verify the metadata of a bitmap image with indexed colorspace.
4025 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata));
Julian Lungerecd063e2017-12-27 10:18:50 -05004026 EXPECT_EQ(7, metadata.marked_content_id);
Jane Liuca898292017-08-16 11:25:35 -04004027 EXPECT_EQ(92u, metadata.width);
4028 EXPECT_EQ(68u, metadata.height);
Lei Zhang351e8b02018-12-20 01:10:06 +00004029 EXPECT_FLOAT_EQ(96.0f, metadata.horizontal_dpi);
4030 EXPECT_FLOAT_EQ(96.0f, metadata.vertical_dpi);
Jane Liuca898292017-08-16 11:25:35 -04004031 EXPECT_EQ(1u, metadata.bits_per_pixel);
4032 EXPECT_EQ(FPDF_COLORSPACE_INDEXED, metadata.colorspace);
4033
4034 // Verify the metadata of an image with RGB colorspace.
4035 obj = FPDFPage_GetObject(page, 37);
4036 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
4037 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata));
Julian Lungerecd063e2017-12-27 10:18:50 -05004038 EXPECT_EQ(9, metadata.marked_content_id);
Jane Liuca898292017-08-16 11:25:35 -04004039 EXPECT_EQ(126u, metadata.width);
4040 EXPECT_EQ(106u, metadata.height);
Lei Zhang351e8b02018-12-20 01:10:06 +00004041 EXPECT_FLOAT_EQ(162.173752f, metadata.horizontal_dpi);
4042 EXPECT_FLOAT_EQ(162.555878f, metadata.vertical_dpi);
Jane Liuca898292017-08-16 11:25:35 -04004043 EXPECT_EQ(24u, metadata.bits_per_pixel);
4044 EXPECT_EQ(FPDF_COLORSPACE_DEVICERGB, metadata.colorspace);
4045
4046 UnloadPage(page);
4047}
Lei Zhangdc1b7392020-05-14 21:15:53 +00004048
4049TEST_F(FPDFEditEmbedderTest, GetImageMetadataJpxLzw) {
4050 ASSERT_TRUE(OpenDocument("jpx_lzw.pdf"));
4051 FPDF_PAGE page = LoadPage(0);
4052 ASSERT_TRUE(page);
4053
4054 FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
4055 ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
4056
4057 FPDF_IMAGEOBJ_METADATA metadata;
4058 ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata));
4059 EXPECT_EQ(-1, metadata.marked_content_id);
4060 EXPECT_EQ(612u, metadata.width);
4061 EXPECT_EQ(792u, metadata.height);
4062 EXPECT_FLOAT_EQ(72.0f, metadata.horizontal_dpi);
4063 EXPECT_FLOAT_EQ(72.0f, metadata.vertical_dpi);
4064 EXPECT_EQ(24u, metadata.bits_per_pixel);
4065 EXPECT_EQ(FPDF_COLORSPACE_UNKNOWN, metadata.colorspace);
4066
4067 UnloadPage(page);
4068}