Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cpdf_pagecontentgenerator_unittest.cpp
Go to the documentation of this file.
1// Copyright 2017 The PDFium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "core/fpdfapi/edit/cpdf_pagecontentgenerator.h"
6
7#include <iterator>
8#include <memory>
9#include <utility>
10
11#include "core/fpdfapi/font/cpdf_font.h"
12#include "core/fpdfapi/page/cpdf_colorspace.h"
13#include "core/fpdfapi/page/cpdf_docpagedata.h"
14#include "core/fpdfapi/page/cpdf_form.h"
15#include "core/fpdfapi/page/cpdf_page.h"
16#include "core/fpdfapi/page/cpdf_pathobject.h"
17#include "core/fpdfapi/page/cpdf_textobject.h"
18#include "core/fpdfapi/page/cpdf_textstate.h"
19#include "core/fpdfapi/page/test_with_page_module.h"
20#include "core/fpdfapi/parser/cpdf_dictionary.h"
21#include "core/fpdfapi/parser/cpdf_document.h"
22#include "core/fpdfapi/parser/cpdf_name.h"
23#include "core/fpdfapi/parser/cpdf_parser.h"
24#include "core/fpdfapi/parser/cpdf_reference.h"
25#include "core/fpdfapi/parser/cpdf_stream.h"
26#include "core/fpdfapi/parser/cpdf_test_document.h"
27#include "core/fxcrt/data_vector.h"
28#include "core/fxge/cfx_fillrenderoptions.h"
29#include "testing/gtest/include/gtest/gtest.h"
30
32 protected:
34 fxcrt::ostringstream* buf,
35 CPDF_PathObject* pPathObj) {
36 pGen->ProcessPath(buf, pPathObj);
37 }
38
41 const ByteString& type,
42 const ByteString& name) {
43 RetainPtr<const CPDF_Dictionary> pResources =
44 pGen->m_pObjHolder->GetResources();
45 return pResources->GetDictFor(type)->GetDictFor(name);
46 }
47
49 fxcrt::ostringstream* buf,
50 CPDF_TextObject* pTextObj) {
51 pGen->ProcessText(buf, pTextObj);
52 }
53};
54
56 auto pPathObj = std::make_unique<CPDF_PathObject>();
57 pPathObj->set_stroke(true);
58 pPathObj->set_filltype(CFX_FillRenderOptions::FillType::kEvenOdd);
59 pPathObj->path().AppendRect(10, 5, 13, 30);
60
61 auto dummy_page_dict = pdfium::MakeRetain<CPDF_Dictionary>();
62 auto pTestPage = pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict);
63 CPDF_PageContentGenerator generator(pTestPage.Get());
64 fxcrt::ostringstream buf;
65 TestProcessPath(&generator, &buf, pPathObj.get());
66 EXPECT_EQ("q 10 5 3 25 re B* Q\n", ByteString(buf));
67
68 pPathObj = std::make_unique<CPDF_PathObject>();
69 pPathObj->path().AppendPoint(CFX_PointF(0, 0), CFX_Path::Point::Type::kMove);
70 pPathObj->path().AppendPoint(CFX_PointF(5.2f, 0),
72 pPathObj->path().AppendPoint(CFX_PointF(5.2f, 3.78f),
74 pPathObj->path().AppendPointAndClose(CFX_PointF(0, 3.78f),
76 buf.str("");
77 TestProcessPath(&generator, &buf, pPathObj.get());
78 EXPECT_EQ("q 0 0 5.1999998 3.78 re n Q\n", ByteString(buf));
79}
80
82 static const std::vector<float> rgb = {0.000000000000000000001f, 0.7f, 0.35f};
84 CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceRGB);
85 {
86 auto pPathObj = std::make_unique<CPDF_PathObject>();
87 pPathObj->set_filltype(CFX_FillRenderOptions::FillType::kWinding);
88
89 // Test code in ProcessPath that generates re operator
90 pPathObj->path().AppendRect(0.000000000000000000001,
91 0.000000000000000000001, 100, 100);
92
93 pPathObj->mutable_color_state().SetFillColor(pCS, rgb);
94 pPathObj->mutable_color_state().SetStrokeColor(pCS, rgb);
95 pPathObj->mutable_graph_state().SetLineWidth(200000000000000000001.0);
96 pPathObj->Transform(CFX_Matrix(1, 0, 0, 1, 0.000000000000000000001,
97 200000000000000.000002));
98
99 auto dummy_page_dict = pdfium::MakeRetain<CPDF_Dictionary>();
100 auto pTestPage = pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict);
101 CPDF_PageContentGenerator generator(pTestPage.Get());
102 fxcrt::ostringstream buf;
103 TestProcessPath(&generator, &buf, pPathObj.get());
104 EXPECT_EQ(
105 "q .00000000000000000000099999997 .69999999 .34999999 rg "
106 ".00000000000000000000099999997 .69999999 .34999999 RG "
107 "200000000000000000000 w 1 0 0 1 .00000000000000000000099999997 "
108 "200000000000000 cm .00000000000000000000099999997 "
109 ".00000000000000000000099999997 100 100 re f Q\n",
110 ByteString(buf));
111 }
112
113 {
114 // Test code in ProcessPath that handles bezier operator
115 auto pPathObj = std::make_unique<CPDF_PathObject>();
116 pPathObj->mutable_color_state().SetFillColor(pCS, rgb);
117 pPathObj->mutable_color_state().SetStrokeColor(pCS, rgb);
118 pPathObj->mutable_graph_state().SetLineWidth(2.000000000000000000001);
119 pPathObj->Transform(CFX_Matrix(1, 0, 0, 1, 432, 500000000000000.000002));
120
121 pPathObj->set_filltype(CFX_FillRenderOptions::FillType::kWinding);
122 pPathObj->path().AppendPoint(CFX_PointF(0.000000000000000000001f, 4.67f),
124 pPathObj->path().AppendPoint(
125 CFX_PointF(0.000000000000000000001, 100000000000000.000002),
127 pPathObj->path().AppendPoint(CFX_PointF(0.0000000000001f, 3.15f),
129 pPathObj->path().AppendPoint(CFX_PointF(3.57f, 2.98f),
131 pPathObj->path().AppendPointAndClose(
132 CFX_PointF(53.4f, 5000000000000000000.00000000000000004),
134 auto dummy_page_dict = pdfium::MakeRetain<CPDF_Dictionary>();
135 auto pTestPage = pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict);
136 CPDF_PageContentGenerator generator(pTestPage.Get());
137 fxcrt::ostringstream buf;
138
139 TestProcessPath(&generator, &buf, pPathObj.get());
140 EXPECT_EQ(
141 "q .00000000000000000000099999997 .69999999 .34999999 rg "
142 ".00000000000000000000099999997 .69999999 .34999999 RG 2 w 1 0 0 1 432 "
143 "499999990000000 cm .00000000000000000000099999997 4.6700001 m "
144 ".00000000000000000000099999997 100000000000000 l "
145 ".000000000000099999998 3.1500001 3.5699999 2.98 53.400002 "
146 "5000000000000000000 c h f Q\n",
147 ByteString(buf));
148 }
149}
150
152 auto pPathObj = std::make_unique<CPDF_PathObject>();
153 pPathObj->set_filltype(CFX_FillRenderOptions::FillType::kWinding);
154 pPathObj->path().AppendPoint(CFX_PointF(3.102f, 4.67f),
156 pPathObj->path().AppendPoint(CFX_PointF(5.45f, 0.29f),
158 pPathObj->path().AppendPoint(CFX_PointF(4.24f, 3.15f),
160 pPathObj->path().AppendPoint(CFX_PointF(4.65f, 2.98f),
162 pPathObj->path().AppendPoint(CFX_PointF(3.456f, 0.24f),
164 pPathObj->path().AppendPoint(CFX_PointF(10.6f, 11.15f),
166 pPathObj->path().AppendPoint(CFX_PointF(11, 12.5f),
168 pPathObj->path().AppendPoint(CFX_PointF(11.46f, 12.67f),
170 pPathObj->path().AppendPoint(CFX_PointF(11.84f, 12.96f),
172 pPathObj->path().AppendPointAndClose(CFX_PointF(12, 13.64f),
174
175 auto dummy_page_dict = pdfium::MakeRetain<CPDF_Dictionary>();
176 auto pTestPage = pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict);
177 CPDF_PageContentGenerator generator(pTestPage.Get());
178 fxcrt::ostringstream buf;
179 TestProcessPath(&generator, &buf, pPathObj.get());
180 EXPECT_EQ(
181 "q 3.102 4.6700001 m 5.4499998 .28999999 l 4.2399998 "
182 "3.1500001 4.6500001 2.98 3.4560001 .23999999 c 10.6000004 11.149999"
183 "6 l 11 12.5 l 11.46 12.6700001 11.8400002 12.96 12 13.6400003 c h f"
184 " Q\n",
185 ByteString(buf));
186}
187
189 auto pPathObj = std::make_unique<CPDF_PathObject>();
190 pPathObj->set_stroke(true);
191 pPathObj->set_filltype(CFX_FillRenderOptions::FillType::kWinding);
192 pPathObj->path().AppendPoint(CFX_PointF(1, 2), CFX_Path::Point::Type::kMove);
193 pPathObj->path().AppendPoint(CFX_PointF(3, 4), CFX_Path::Point::Type::kLine);
194 pPathObj->path().AppendPointAndClose(CFX_PointF(5, 6),
196
197 static const std::vector<float> rgb = {0.5f, 0.7f, 0.35f};
199 CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceRGB);
200 pPathObj->mutable_color_state().SetFillColor(pCS, rgb);
201
202 static const std::vector<float> rgb2 = {1, 0.9f, 0};
203 pPathObj->mutable_color_state().SetStrokeColor(pCS, rgb2);
204 pPathObj->mutable_general_state().SetFillAlpha(0.5f);
205 pPathObj->mutable_general_state().SetStrokeAlpha(0.8f);
206
207 auto pDoc = std::make_unique<CPDF_TestDocument>();
208 pDoc->CreateNewDoc();
209
210 RetainPtr<CPDF_Dictionary> pPageDict(pDoc->CreateNewPage(0));
211 auto pTestPage = pdfium::MakeRetain<CPDF_Page>(pDoc.get(), pPageDict);
212 CPDF_PageContentGenerator generator(pTestPage.Get());
213 fxcrt::ostringstream buf;
214 TestProcessPath(&generator, &buf, pPathObj.get());
215 ByteString path_string(buf);
216
217 // Color RGB values used are integers divided by 255.
218 const ByteStringView kExpectedStringStart =
219 "q .5 .69999999 .34999999 rg 1 .89999998 0 RG /";
220 const ByteStringView kExpectedStringEnd = " gs 1 2 m 3 4 l 5 6 l h B Q\n";
221 const size_t kExpectedStringMinLength =
222 kExpectedStringStart.GetLength() + kExpectedStringEnd.GetLength();
223 EXPECT_EQ(kExpectedStringStart,
224 path_string.First(kExpectedStringStart.GetLength()));
225 EXPECT_EQ(kExpectedStringEnd,
226 path_string.Last(kExpectedStringEnd.GetLength()));
227 ASSERT_GT(path_string.GetLength(), kExpectedStringMinLength);
228 RetainPtr<const CPDF_Dictionary> external_gs = TestGetResource(
229 &generator, "ExtGState",
230 path_string.Substr(kExpectedStringStart.GetLength(),
231 path_string.GetLength() - kExpectedStringMinLength));
232 ASSERT_TRUE(external_gs);
233 EXPECT_EQ(0.5f, external_gs->GetFloatFor("ca"));
234 EXPECT_EQ(0.8f, external_gs->GetFloatFor("CA"));
235
236 // Same path, now with a stroke.
237 pPathObj->mutable_graph_state().SetLineWidth(10.5f);
238 buf.str("");
239 TestProcessPath(&generator, &buf, pPathObj.get());
240 const ByteStringView kExpectedStringStart2 =
241 "q .5 .69999999 .34999999 rg 1 .89999998 0 RG 10.5 w /";
242 ByteString path_string2(buf);
243 EXPECT_EQ(kExpectedStringStart2,
244 path_string2.First(kExpectedStringStart2.GetLength()));
245 EXPECT_EQ(kExpectedStringEnd,
246 path_string2.Last(kExpectedStringEnd.GetLength()));
247
248 // Compare with the previous (should use same dictionary for gs)
249 const size_t kExpectedStringsLengthDifference =
250 kExpectedStringStart2.GetLength() - kExpectedStringStart.GetLength();
251 EXPECT_EQ(path_string.GetLength() + kExpectedStringsLengthDifference,
252 path_string2.GetLength());
253 EXPECT_EQ(
254 path_string.Substr(kExpectedStringStart.GetLength(),
255 path_string.GetLength() - kExpectedStringMinLength),
256 path_string2.Substr(kExpectedStringStart2.GetLength(),
257 path_string2.GetLength() - kExpectedStringMinLength -
258 kExpectedStringsLengthDifference));
259}
260
262 // Checking font whose font dictionary is not yet indirect object.
263 auto pDoc = std::make_unique<CPDF_TestDocument>();
264 pDoc->CreateNewDoc();
265
266 RetainPtr<CPDF_Dictionary> pPageDict(pDoc->CreateNewPage(0));
267 auto pTestPage = pdfium::MakeRetain<CPDF_Page>(pDoc.get(), pPageDict);
268 CPDF_PageContentGenerator generator(pTestPage.Get());
269 auto pTextObj = std::make_unique<CPDF_TextObject>();
270 pTextObj->mutable_text_state().SetFont(
271 CPDF_Font::GetStockFont(pDoc.get(), "Times-Roman"));
272 pTextObj->mutable_text_state().SetFontSize(10.0f);
273
274 static const std::vector<float> rgb = {0.5f, 0.7f, 0.35f};
276 CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceRGB);
277 pTextObj->mutable_color_state().SetFillColor(pCS, rgb);
278
279 static const std::vector<float> rgb2 = {1, 0.9f, 0};
280 pTextObj->mutable_color_state().SetStrokeColor(pCS, rgb2);
281 pTextObj->mutable_general_state().SetFillAlpha(0.5f);
282 pTextObj->mutable_general_state().SetStrokeAlpha(0.8f);
283 pTextObj->Transform(CFX_Matrix(1, 0, 0, 1, 100, 100));
284 pTextObj->SetText("Hello World");
285 fxcrt::ostringstream buf;
286 TestProcessText(&generator, &buf, pTextObj.get());
287 ByteString text_string(buf);
288 auto first_resource_at = text_string.Find('/');
289 ASSERT_TRUE(first_resource_at.has_value());
290 first_resource_at = first_resource_at.value() + 1;
291 auto second_resource_at = text_string.ReverseFind('/');
292 ASSERT_TRUE(second_resource_at.has_value());
293 second_resource_at = second_resource_at.value() + 1;
294 ByteString first_string = text_string.First(first_resource_at.value());
295 ByteString mid_string = text_string.Substr(
296 first_resource_at.value(),
297 second_resource_at.value() - first_resource_at.value());
298 ByteString last_string =
299 text_string.Last(text_string.GetLength() - second_resource_at.value());
300 // q and Q must be outside the BT .. ET operations
301 const ByteString kCompareString1 =
302 "q .5 .69999999 .34999999 rg 1 .89999998 0 RG /";
303 // Color RGB values used are integers divided by 255.
304 const ByteString kCompareString2 = " gs BT 1 0 0 1 100 100 Tm /";
305 const ByteString kCompareString3 =
306 " 10 Tf 0 Tr <48656C6C6F20576F726C64> Tj ET Q\n";
307 EXPECT_LT(kCompareString1.GetLength() + kCompareString2.GetLength() +
308 kCompareString3.GetLength(),
309 text_string.GetLength());
310 EXPECT_EQ(kCompareString1, first_string.First(kCompareString1.GetLength()));
311 EXPECT_EQ(kCompareString2, mid_string.Last(kCompareString2.GetLength()));
312 EXPECT_EQ(kCompareString3, last_string.Last(kCompareString3.GetLength()));
313 RetainPtr<const CPDF_Dictionary> external_gs = TestGetResource(
314 &generator, "ExtGState",
315 mid_string.First(mid_string.GetLength() - kCompareString2.GetLength()));
316 ASSERT_TRUE(external_gs);
317 EXPECT_EQ(0.5f, external_gs->GetFloatFor("ca"));
318 EXPECT_EQ(0.8f, external_gs->GetFloatFor("CA"));
319 RetainPtr<const CPDF_Dictionary> font_dict = TestGetResource(
320 &generator, "Font",
321 last_string.First(last_string.GetLength() - kCompareString3.GetLength()));
322 ASSERT_TRUE(font_dict);
323 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
324 EXPECT_EQ("Type1", font_dict->GetNameFor("Subtype"));
325 EXPECT_EQ("Times-Roman", font_dict->GetNameFor("BaseFont"));
326}
327
329 // Checking font whose font dictionary is already an indirect object.
330 auto pDoc = std::make_unique<CPDF_TestDocument>();
331 pDoc->CreateNewDoc();
332
333 RetainPtr<CPDF_Dictionary> pPageDict(pDoc->CreateNewPage(0));
334 auto pTestPage = pdfium::MakeRetain<CPDF_Page>(pDoc.get(), pPageDict);
335 CPDF_PageContentGenerator generator(pTestPage.Get());
336
337 fxcrt::ostringstream buf;
338 {
339 // Set the text object font and text
340 auto pTextObj = std::make_unique<CPDF_TextObject>();
341 auto pDict = pDoc->NewIndirect<CPDF_Dictionary>();
342 pDict->SetNewFor<CPDF_Name>("Type", "Font");
343 pDict->SetNewFor<CPDF_Name>("Subtype", "TrueType");
344
345 RetainPtr<CPDF_Font> pFont = CPDF_Font::GetStockFont(pDoc.get(), "Arial");
346 pDict->SetNewFor<CPDF_Name>("BaseFont", pFont->GetBaseFontName());
347
348 auto pDesc = pDoc->NewIndirect<CPDF_Dictionary>();
349 pDesc->SetNewFor<CPDF_Name>("Type", "FontDescriptor");
350 pDesc->SetNewFor<CPDF_Name>("FontName", pFont->GetBaseFontName());
351 pDict->SetNewFor<CPDF_Reference>("FontDescriptor", pDoc.get(),
352 pDesc->GetObjNum());
353
354 pTextObj->mutable_text_state().SetFont(
355 CPDF_DocPageData::FromDocument(pDoc.get())->GetFont(pDict));
356 pTextObj->mutable_text_state().SetFontSize(15.5f);
357 pTextObj->SetText("I am indirect");
358 pTextObj->SetTextRenderMode(TextRenderingMode::MODE_FILL_CLIP);
359
360 // Add a clipping path.
361 auto pPath = std::make_unique<CPDF_Path>();
362 pPath->AppendPoint(CFX_PointF(0, 0), CFX_Path::Point::Type::kMove);
363 pPath->AppendPoint(CFX_PointF(5, 0), CFX_Path::Point::Type::kLine);
364 pPath->AppendPoint(CFX_PointF(5, 4), CFX_Path::Point::Type::kLine);
365 pPath->AppendPointAndClose(CFX_PointF(0, 4), CFX_Path::Point::Type::kLine);
366 CPDF_ClipPath& clip_path = pTextObj->mutable_clip_path();
367 clip_path.Emplace();
369
370 TestProcessText(&generator, &buf, pTextObj.get());
371 }
372
373 ByteString text_string(buf);
374 auto first_resource_at = text_string.Find('/');
375 ASSERT_TRUE(first_resource_at.has_value());
376 first_resource_at = first_resource_at.value() + 1;
377 ByteString first_string = text_string.First(first_resource_at.value());
378 ByteString last_string =
379 text_string.Last(text_string.GetLength() - first_resource_at.value());
380 // q and Q must be outside the BT .. ET operations
381 ByteString compare_string1 = "q 0 0 5 4 re W* n BT /";
382 ByteString compare_string2 =
383 " 15.5 Tf 4 Tr <4920616D20696E646972656374> Tj ET Q\n";
384 EXPECT_LT(compare_string1.GetLength() + compare_string2.GetLength(),
385 text_string.GetLength());
386 EXPECT_EQ(compare_string1, text_string.First(compare_string1.GetLength()));
387 EXPECT_EQ(compare_string2, text_string.Last(compare_string2.GetLength()));
388 RetainPtr<const CPDF_Dictionary> font_dict = TestGetResource(
389 &generator, "Font",
390 text_string.Substr(compare_string1.GetLength(),
391 text_string.GetLength() - compare_string1.GetLength() -
392 compare_string2.GetLength()));
393 ASSERT_TRUE(font_dict);
394 EXPECT_TRUE(font_dict->GetObjNum());
395 EXPECT_EQ("Font", font_dict->GetNameFor("Type"));
396 EXPECT_EQ("TrueType", font_dict->GetNameFor("Subtype"));
397 EXPECT_EQ("Helvetica", font_dict->GetNameFor("BaseFont"));
398 RetainPtr<const CPDF_Dictionary> font_desc =
399 font_dict->GetDictFor("FontDescriptor");
400 ASSERT_TRUE(font_desc);
401 EXPECT_TRUE(font_desc->GetObjNum());
402 EXPECT_EQ("FontDescriptor", font_desc->GetNameFor("Type"));
403 EXPECT_EQ("Helvetica", font_desc->GetNameFor("FontName"));
404}
405
407 auto pDoc = std::make_unique<CPDF_TestDocument>();
408 pDoc->CreateNewDoc();
409 auto pStream =
410 pdfium::MakeRetain<CPDF_Stream>(pdfium::MakeRetain<CPDF_Dictionary>());
411
412 // Create an empty form.
413 auto pTestForm = std::make_unique<CPDF_Form>(pDoc.get(), nullptr, pStream);
414 pTestForm->ParseContent();
416 pTestForm->GetParseState());
417
418 // The generated stream for the empty form should be an empty string.
419 CPDF_PageContentGenerator generator(pTestForm.get());
420 fxcrt::ostringstream buf;
421 generator.ProcessPageObjects(&buf);
422 EXPECT_EQ("", ByteString(buf));
423}
424
426 auto pDoc = std::make_unique<CPDF_TestDocument>();
427 pDoc->CreateNewDoc();
428 static constexpr uint8_t kContents[] =
429 "q 3.102 4.6700001 m 5.4500012 .28999999 "
430 "l 4.2399998 3.1499999 4.65 2.98 3.456 0.24 c 3.102 4.6700001 l h f Q\n";
431 auto pStream = pdfium::MakeRetain<CPDF_Stream>(
432 DataVector<uint8_t>(std::begin(kContents), std::end(kContents)),
433 pdfium::MakeRetain<CPDF_Dictionary>());
434
435 // Create a form with a non-empty stream.
436 auto pTestForm = std::make_unique<CPDF_Form>(pDoc.get(), nullptr, pStream);
437 pTestForm->ParseContent();
439 pTestForm->GetParseState());
440
441 CPDF_PageContentGenerator generator(pTestForm.get());
442 fxcrt::ostringstream process_buf;
443 generator.ProcessPageObjects(&process_buf);
444 EXPECT_EQ(
445 "q 3.102 4.6700001 m 5.4500012 .28999999 l 4.2399998 3.14"
446 "99999 4.6500001 2.98 3.4560001 .24000001 c 3.102 4.6700001 l h f Q\n",
447 ByteString(process_buf));
448}
fxcrt::ByteString ByteString
Definition bytestring.h:180
constexpr CFX_Matrix(float a1, float b1, float c1, float d1, float e1, float f1)
void TestProcessText(CPDF_PageContentGenerator *pGen, fxcrt::ostringstream *buf, CPDF_TextObject *pTextObj)
void TestProcessPath(CPDF_PageContentGenerator *pGen, fxcrt::ostringstream *buf, CPDF_PathObject *pPathObj)
RetainPtr< const CPDF_Dictionary > TestGetResource(CPDF_PageContentGenerator *pGen, const ByteString &type, const ByteString &name)
void AppendPath(CPDF_Path path, CFX_FillRenderOptions::FillType type)
std::map< ByteString, RetainPtr< CPDF_Object >, std::less<> > DictMap
static CPDF_DocPageData * FromDocument(const CPDF_Document *pDoc)
static RetainPtr< CPDF_Font > GetStockFont(CPDF_Document *pDoc, ByteStringView fontname)
TEST_F(CPDFPageContentGeneratorTest, ProcessRect)
TextRenderingMode
fxcrt::ByteStringView ByteStringView