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
fpdf_parser_decode.cpp
Go to the documentation of this file.
1// Copyright 2014 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// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "core/fpdfapi/parser/fpdf_parser_decode.h"
8
9#include <ctype.h>
10#include <limits.h>
11#include <stddef.h>
12
13#include <algorithm>
14#include <utility>
15
16#include "build/build_config.h"
17#include "constants/stream_dict_common.h"
18#include "core/fpdfapi/parser/cpdf_array.h"
19#include "core/fpdfapi/parser/cpdf_dictionary.h"
20#include "core/fpdfapi/parser/fpdf_parser_utility.h"
21#include "core/fxcodec/fax/faxmodule.h"
22#include "core/fxcodec/flate/flatemodule.h"
23#include "core/fxcodec/scanlinedecoder.h"
24#include "core/fxcrt/fx_extension.h"
25#include "core/fxcrt/fx_safe_types.h"
26#include "core/fxcrt/span_util.h"
27#include "core/fxcrt/utf16.h"
28#include "third_party/base/check.h"
29#include "third_party/base/containers/contains.h"
30
31namespace {
32
33const uint32_t kMaxStreamSize = 20 * 1024 * 1024;
34
35bool CheckFlateDecodeParams(int Colors, int BitsPerComponent, int Columns) {
36 if (Colors < 0 || BitsPerComponent < 0 || Columns < 0)
37 return false;
38
39 FX_SAFE_INT32 check = Columns;
40 check *= Colors;
41 check *= BitsPerComponent;
42 if (!check.IsValid())
43 return false;
44
45 return check.ValueOrDie() <= INT_MAX - 7;
46}
47
48uint8_t GetA85Result(uint32_t res, size_t i) {
49 return static_cast<uint8_t>(res >> (3 - i) * 8);
50}
51
52} // namespace
53
54const uint16_t kPDFDocEncoding[256] = {
55 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
56 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011,
57 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x02d8, 0x02c7, 0x02c6,
58 0x02d9, 0x02dd, 0x02db, 0x02da, 0x02dc, 0x0020, 0x0021, 0x0022, 0x0023,
59 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c,
60 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
61 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e,
62 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
63 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
64 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
65 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062,
66 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b,
67 0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
68 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d,
69 0x007e, 0x0000, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192,
70 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018,
71 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x0141, 0x0152, 0x0160, 0x0178,
72 0x017d, 0x0131, 0x0142, 0x0153, 0x0161, 0x017e, 0x0000, 0x20ac, 0x00a1,
73 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa,
74 0x00ab, 0x00ac, 0x0000, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b2, 0x00b3,
75 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc,
76 0x00bd, 0x00be, 0x00bf, 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5,
77 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce,
78 0x00cf, 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
79 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, 0x00e0,
80 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9,
81 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f2,
82 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb,
83 0x00fc, 0x00fd, 0x00fe, 0x00ff};
84
85bool ValidateDecoderPipeline(const CPDF_Array* pDecoders) {
86 size_t count = pDecoders->size();
87 if (count == 0)
88 return true;
89
90 for (size_t i = 0; i < count; ++i) {
91 RetainPtr<const CPDF_Object> object = pDecoders->GetDirectObjectAt(i);
92 if (!object || !object->IsName()) {
93 return false;
94 }
95 }
96
97 if (count == 1)
98 return true;
99
100 // TODO(thestig): Consolidate all the places that use these filter names.
101 static const char kValidDecoders[][16] = {
102 "FlateDecode", "Fl", "LZWDecode", "LZW", "ASCII85Decode", "A85",
103 "ASCIIHexDecode", "AHx", "RunLengthDecode", "RL"};
104 for (size_t i = 0; i < count - 1; ++i) {
105 if (!pdfium::Contains(kValidDecoders, pDecoders->GetByteStringAt(i)))
106 return false;
107 }
108 return true;
109}
110
111uint32_t A85Decode(pdfium::span<const uint8_t> src_span,
112 std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
113 uint32_t* dest_size) {
114 *dest_size = 0;
115 if (src_span.empty()) {
116 dest_buf->reset();
117 return 0;
118 }
119
120 // Count legal characters and zeros.
121 uint32_t zcount = 0;
122 uint32_t pos = 0;
123 while (pos < src_span.size()) {
124 uint8_t ch = src_span[pos];
125 if (ch == 'z') {
126 zcount++;
127 } else if ((ch < '!' || ch > 'u') && !PDFCharIsLineEnding(ch) &&
128 ch != ' ' && ch != '\t') {
129 break;
130 }
131 pos++;
132 }
133 // No content to decode.
134 if (pos == 0)
135 return 0;
136
137 // Count the space needed to contain non-zero characters. The encoding ratio
138 // of Ascii85 is 4:5.
139 uint32_t space_for_non_zeroes = (pos - zcount) / 5 * 4 + 4;
140 FX_SAFE_UINT32 size = zcount;
141 size *= 4;
142 size += space_for_non_zeroes;
143 if (!size.IsValid())
144 return FX_INVALID_OFFSET;
145
146 dest_buf->reset(FX_Alloc(uint8_t, size.ValueOrDie()));
147 uint8_t* dest_buf_ptr = dest_buf->get();
148 size_t state = 0;
149 uint32_t res = 0;
150 pos = 0;
151 while (pos < src_span.size()) {
152 uint8_t ch = src_span[pos++];
153 if (PDFCharIsLineEnding(ch) || ch == ' ' || ch == '\t')
154 continue;
155
156 if (ch == 'z') {
157 memset(dest_buf_ptr + *dest_size, 0, 4);
158 state = 0;
159 res = 0;
160 *dest_size += 4;
161 continue;
162 }
163
164 // Check for the end or illegal character.
165 if (ch < '!' || ch > 'u')
166 break;
167
168 res = res * 85 + ch - 33;
169 if (state < 4) {
170 ++state;
171 continue;
172 }
173
174 for (size_t i = 0; i < 4; ++i) {
175 dest_buf_ptr[(*dest_size)++] = GetA85Result(res, i);
176 }
177 state = 0;
178 res = 0;
179 }
180 // Handle partial group.
181 if (state) {
182 for (size_t i = state; i < 5; ++i)
183 res = res * 85 + 84;
184 for (size_t i = 0; i < state - 1; ++i)
185 dest_buf_ptr[(*dest_size)++] = GetA85Result(res, i);
186 }
187 if (pos < src_span.size() && src_span[pos] == '>')
188 ++pos;
189 return pos;
190}
191
192uint32_t HexDecode(pdfium::span<const uint8_t> src_span,
193 std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
194 uint32_t* dest_size) {
195 *dest_size = 0;
196 if (src_span.empty()) {
197 dest_buf->reset();
198 return 0;
199 }
200
201 uint32_t i = 0;
202 // Find the end of data.
203 while (i < src_span.size() && src_span[i] != '>')
204 ++i;
205
206 dest_buf->reset(FX_Alloc(uint8_t, i / 2 + 1));
207 uint8_t* dest_buf_ptr = dest_buf->get();
208 bool bFirst = true;
209 for (i = 0; i < src_span.size(); ++i) {
210 uint8_t ch = src_span[i];
211 if (PDFCharIsLineEnding(ch) || ch == ' ' || ch == '\t')
212 continue;
213
214 if (ch == '>') {
215 ++i;
216 break;
217 }
218 if (!isxdigit(ch))
219 continue;
220
221 int digit = FXSYS_HexCharToInt(ch);
222 if (bFirst)
223 dest_buf_ptr[*dest_size] = digit * 16;
224 else
225 dest_buf_ptr[(*dest_size)++] += digit;
226 bFirst = !bFirst;
227 }
228 if (!bFirst)
229 ++(*dest_size);
230 return i;
231}
232
233uint32_t RunLengthDecode(pdfium::span<const uint8_t> src_span,
234 std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
235 uint32_t* dest_size) {
236 size_t i = 0;
237 *dest_size = 0;
238 while (i < src_span.size()) {
239 if (src_span[i] == 128)
240 break;
241
242 uint32_t old = *dest_size;
243 if (src_span[i] < 128) {
244 *dest_size += src_span[i] + 1;
245 if (*dest_size < old)
246 return FX_INVALID_OFFSET;
247 i += src_span[i] + 2;
248 } else {
249 *dest_size += 257 - src_span[i];
250 if (*dest_size < old)
251 return FX_INVALID_OFFSET;
252 i += 2;
253 }
254 }
255 if (*dest_size >= kMaxStreamSize)
256 return FX_INVALID_OFFSET;
257
258 dest_buf->reset(FX_Alloc(uint8_t, *dest_size));
259 pdfium::span<uint8_t> dest_span(dest_buf->get(), *dest_size);
260 i = 0;
261 int dest_count = 0;
262 while (i < src_span.size()) {
263 if (src_span[i] == 128)
264 break;
265
266 if (src_span[i] < 128) {
267 uint32_t copy_len = src_span[i] + 1;
268 uint32_t buf_left = src_span.size() - i - 1;
269 if (buf_left < copy_len) {
270 uint32_t delta = copy_len - buf_left;
271 copy_len = buf_left;
272 fxcrt::spanclr(dest_span.subspan(dest_count + copy_len, delta));
273 }
274 auto copy_span = src_span.subspan(i + 1, copy_len);
275 fxcrt::spancpy(dest_span.subspan(dest_count), copy_span);
276 dest_count += src_span[i] + 1;
277 i += src_span[i] + 2;
278 } else {
279 const uint8_t fill = i + 1 < src_span.size() ? src_span[i + 1] : 0;
280 const size_t fill_size = 257 - src_span[i];
281 fxcrt::spanset(dest_span.subspan(dest_count, fill_size), fill);
282 dest_count += fill_size;
283 i += 2;
284 }
285 }
286 return std::min(i + 1, src_span.size());
287}
288
290 pdfium::span<const uint8_t> src_span,
291 int width,
292 int height,
293 const CPDF_Dictionary* pParams) {
294 int K = 0;
295 bool EndOfLine = false;
296 bool ByteAlign = false;
297 bool BlackIs1 = false;
298 int Columns = 1728;
299 int Rows = 0;
300 if (pParams) {
301 K = pParams->GetIntegerFor("K");
302 EndOfLine = !!pParams->GetIntegerFor("EndOfLine");
303 ByteAlign = !!pParams->GetIntegerFor("EncodedByteAlign");
304 BlackIs1 = !!pParams->GetIntegerFor("BlackIs1");
305 Columns = pParams->GetIntegerFor("Columns", 1728);
306 Rows = pParams->GetIntegerFor("Rows");
307 if (Rows > USHRT_MAX)
308 Rows = 0;
309 }
310 return FaxModule::CreateDecoder(src_span, width, height, K, EndOfLine,
311 ByteAlign, BlackIs1, Columns, Rows);
312}
313
315 pdfium::span<const uint8_t> src_span,
316 int width,
317 int height,
318 int nComps,
319 int bpc,
320 const CPDF_Dictionary* pParams) {
321 int predictor = 0;
322 int Colors = 0;
323 int BitsPerComponent = 0;
324 int Columns = 0;
325 if (pParams) {
326 predictor = pParams->GetIntegerFor("Predictor");
327 Colors = pParams->GetIntegerFor("Colors", 1);
328 BitsPerComponent = pParams->GetIntegerFor("BitsPerComponent", 8);
329 Columns = pParams->GetIntegerFor("Columns", 1);
330 if (!CheckFlateDecodeParams(Colors, BitsPerComponent, Columns))
331 return nullptr;
332 }
333 return FlateModule::CreateDecoder(src_span, width, height, nComps, bpc,
334 predictor, Colors, BitsPerComponent,
335 Columns);
336}
337
338uint32_t FlateOrLZWDecode(bool bLZW,
339 pdfium::span<const uint8_t> src_span,
340 const CPDF_Dictionary* pParams,
341 uint32_t estimated_size,
342 std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
343 uint32_t* dest_size) {
344 int predictor = 0;
345 int Colors = 0;
346 int BitsPerComponent = 0;
347 int Columns = 0;
348 bool bEarlyChange = true;
349 if (pParams) {
350 predictor = pParams->GetIntegerFor("Predictor");
351 bEarlyChange = !!pParams->GetIntegerFor("EarlyChange", 1);
352 Colors = pParams->GetIntegerFor("Colors", 1);
353 BitsPerComponent = pParams->GetIntegerFor("BitsPerComponent", 8);
354 Columns = pParams->GetIntegerFor("Columns", 1);
355 if (!CheckFlateDecodeParams(Colors, BitsPerComponent, Columns))
356 return FX_INVALID_OFFSET;
357 }
358 return FlateModule::FlateOrLZWDecode(bLZW, src_span, bEarlyChange, predictor,
359 Colors, BitsPerComponent, Columns,
360 estimated_size, dest_buf, dest_size);
361}
362
364 RetainPtr<const CPDF_Dictionary> pDict) {
365 RetainPtr<const CPDF_Object> pFilter = pDict->GetDirectObjectFor("Filter");
366 if (!pFilter)
367 return DecoderArray();
368
369 if (!pFilter->IsArray() && !pFilter->IsName())
370 return absl::nullopt;
371
372 RetainPtr<const CPDF_Object> pParams =
373 pDict->GetDirectObjectFor(pdfium::stream::kDecodeParms);
374
375 DecoderArray decoder_array;
376 if (const CPDF_Array* pDecoders = pFilter->AsArray()) {
377 if (!ValidateDecoderPipeline(pDecoders))
378 return absl::nullopt;
379
380 RetainPtr<const CPDF_Array> pParamsArray = ToArray(pParams);
381 for (size_t i = 0; i < pDecoders->size(); ++i) {
382 decoder_array.emplace_back(
383 pDecoders->GetByteStringAt(i),
384 pParamsArray ? pParamsArray->GetDictAt(i) : nullptr);
385 }
386 } else {
387 DCHECK(pFilter->IsName());
388 decoder_array.emplace_back(pFilter->GetString(),
389 pParams ? pParams->GetDict() : nullptr);
390 }
391
392 return decoder_array;
393}
394
395bool PDF_DataDecode(pdfium::span<const uint8_t> src_span,
396 uint32_t last_estimated_size,
397 bool bImageAcc,
398 const DecoderArray& decoder_array,
399 std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
400 uint32_t* dest_size,
401 ByteString* ImageEncoding,
402 RetainPtr<const CPDF_Dictionary>* pImageParams) {
403 std::unique_ptr<uint8_t, FxFreeDeleter> result;
404 // May be changed to point to |result| in the for-loop below. So put it below
405 // |result| and let it get destroyed first.
406 pdfium::span<const uint8_t> last_span = src_span;
407 size_t nSize = decoder_array.size();
408 for (size_t i = 0; i < nSize; ++i) {
409 int estimated_size = i == nSize - 1 ? last_estimated_size : 0;
410 ByteString decoder = decoder_array[i].first;
411 RetainPtr<const CPDF_Dictionary> pParam =
412 ToDictionary(decoder_array[i].second);
413 std::unique_ptr<uint8_t, FxFreeDeleter> new_buf;
414 uint32_t new_size = 0xFFFFFFFF;
415 uint32_t offset = FX_INVALID_OFFSET;
416 if (decoder == "Crypt")
417 continue;
418 if (decoder == "FlateDecode" || decoder == "Fl") {
419 if (bImageAcc && i == nSize - 1) {
420 *ImageEncoding = "FlateDecode";
421 *dest_buf = std::move(result);
422 *dest_size = last_span.size();
423 *pImageParams = std::move(pParam);
424 return true;
425 }
426 offset = FlateOrLZWDecode(false, last_span, pParam, estimated_size,
427 &new_buf, &new_size);
428 } else if (decoder == "LZWDecode" || decoder == "LZW") {
429 offset = FlateOrLZWDecode(true, last_span, pParam, estimated_size,
430 &new_buf, &new_size);
431 } else if (decoder == "ASCII85Decode" || decoder == "A85") {
432 offset = A85Decode(last_span, &new_buf, &new_size);
433 } else if (decoder == "ASCIIHexDecode" || decoder == "AHx") {
434 offset = HexDecode(last_span, &new_buf, &new_size);
435 } else if (decoder == "RunLengthDecode" || decoder == "RL") {
436 if (bImageAcc && i == nSize - 1) {
437 *ImageEncoding = "RunLengthDecode";
438 *dest_buf = std::move(result);
439 *dest_size = last_span.size();
440 *pImageParams = std::move(pParam);
441 return true;
442 }
443 offset = RunLengthDecode(last_span, &new_buf, &new_size);
444 } else {
445 // If we get here, assume it's an image decoder.
446 if (decoder == "DCT")
447 decoder = "DCTDecode";
448 else if (decoder == "CCF")
449 decoder = "CCITTFaxDecode";
450 *ImageEncoding = std::move(decoder);
451 *pImageParams = std::move(pParam);
452 *dest_buf = std::move(result);
453 *dest_size = last_span.size();
454 return true;
455 }
456 if (offset == FX_INVALID_OFFSET)
457 return false;
458
459 last_span = {new_buf.get(), new_size};
460 result = std::move(new_buf);
461 }
462 ImageEncoding->clear();
463 *pImageParams = nullptr;
464 *dest_buf = std::move(result);
465 *dest_size = last_span.size();
466 return true;
467}
468
469static size_t StripLanguageCodes(pdfium::span<wchar_t> s, size_t n) {
470 size_t dest_pos = 0;
471 for (size_t i = 0; i < n; ++i) {
472 // 0x001B is a begin/end marker for language metadata region that
473 // should not be in the decoded text.
474 if (s[i] == 0x001B) {
475 for (++i; i < n && s[i] != 0x001B; ++i) {
476 // No for-loop body. The loop searches for the terminating 0x001B.
477 }
478 continue;
479 }
480 s[dest_pos++] = s[i];
481 }
482 return dest_pos;
483}
484
485WideString PDF_DecodeText(pdfium::span<const uint8_t> span) {
486 size_t dest_pos = 0;
487 WideString result;
488 if (span.size() >= 2 && ((span[0] == 0xfe && span[1] == 0xff) ||
489 (span[0] == 0xff && span[1] == 0xfe))) {
490 if (span[0] == 0xfe) {
491 result = WideString::FromUTF16BE(span.subspan(2));
492 } else {
493 result = WideString::FromUTF16LE(span.subspan(2));
494 }
495 pdfium::span<wchar_t> dest_buf = result.GetBuffer(result.GetLength());
496 dest_pos = StripLanguageCodes(dest_buf, result.GetLength());
497 } else if (span.size() >= 3 && span[0] == 0xef && span[1] == 0xbb &&
498 span[2] == 0xbf) {
499 result = WideString::FromUTF8(span.subspan(3));
500 pdfium::span<wchar_t> dest_buf = result.GetBuffer(result.GetLength());
501 dest_pos = StripLanguageCodes(dest_buf, result.GetLength());
502 } else {
503 pdfium::span<wchar_t> dest_buf = result.GetBuffer(span.size());
504 for (size_t i = 0; i < span.size(); ++i)
505 dest_buf[i] = kPDFDocEncoding[span[i]];
506 dest_pos = span.size();
507 }
508 result.ReleaseBuffer(dest_pos);
509 return result;
510}
511
512ByteString PDF_EncodeText(WideStringView str) {
513 size_t i = 0;
514 size_t len = str.GetLength();
515 ByteString result;
516 {
517 pdfium::span<char> dest_buf = result.GetBuffer(len);
518 for (i = 0; i < len; ++i) {
519 int code;
520 for (code = 0; code < 256; ++code) {
521 if (kPDFDocEncoding[code] == str[i])
522 break;
523 }
524 if (code == 256)
525 break;
526
527 dest_buf[i] = code;
528 }
529 }
530 result.ReleaseBuffer(i);
531 if (i == len)
532 return result;
533
534 if (len > INT_MAX / 2 - 1) {
535 result.ReleaseBuffer(0);
536 return result;
537 }
538
539 size_t dest_index = 0;
540 {
541#if defined(WCHAR_T_IS_32_BIT)
542 // 2 or 4 bytes required per UTF-32 code unit.
543 pdfium::span<uint8_t> dest_buf =
544 pdfium::as_writable_bytes(result.GetBuffer(len * 4 + 2));
545#else
546 // 2 bytes required per UTF-16 code unit.
547 pdfium::span<uint8_t> dest_buf =
548 pdfium::as_writable_bytes(result.GetBuffer(len * 2 + 2));
549#endif // defined(WCHAR_T_IS_32_BIT)
550
551 dest_buf[dest_index++] = 0xfe;
552 dest_buf[dest_index++] = 0xff;
553 for (size_t j = 0; j < len; ++j) {
554#if defined(WCHAR_T_IS_32_BIT)
555 if (pdfium::IsSupplementary(str[j])) {
556 pdfium::SurrogatePair pair(str[j]);
557 dest_buf[dest_index++] = pair.high() >> 8;
558 dest_buf[dest_index++] = static_cast<uint8_t>(pair.high());
559 dest_buf[dest_index++] = pair.low() >> 8;
560 dest_buf[dest_index++] = static_cast<uint8_t>(pair.low());
561 continue;
562 }
563#endif // defined(WCHAR_T_IS_32_BIT)
564 dest_buf[dest_index++] = str[j] >> 8;
565 dest_buf[dest_index++] = static_cast<uint8_t>(str[j]);
566 }
567 }
568 result.ReleaseBuffer(dest_index);
569 return result;
570}
571
572ByteString PDF_EncodeString(ByteStringView src) {
573 ByteString result;
574 result.Reserve(src.GetLength() + 2);
575 result += '(';
576 for (size_t i = 0; i < src.GetLength(); ++i) {
577 uint8_t ch = src[i];
578 if (ch == 0x0a) {
579 result += "\\n";
580 continue;
581 }
582 if (ch == 0x0d) {
583 result += "\\r";
584 continue;
585 }
586 if (ch == ')' || ch == '\\' || ch == '(')
587 result += '\\';
588 result += static_cast<char>(ch);
589 }
590 result += ')';
591 return result;
592}
593
594ByteString PDF_HexEncodeString(ByteStringView src) {
595 ByteString result;
596 result.Reserve(2 * src.GetLength() + 2);
597 result += '<';
598 for (size_t i = 0; i < src.GetLength(); ++i) {
599 char buf[2];
600 FXSYS_IntToTwoHexChars(src[i], buf);
601 result += buf[0];
602 result += buf[1];
603 }
604 result += '>';
605 return result;
606}
int GetIntegerFor(const ByteString &key) const
int GetIntegerFor(const ByteString &key, int default_int) const
static uint32_t FlateOrLZWDecode(bool bLZW, pdfium::span< const uint8_t > src_span, bool bEarlyChange, int predictor, int Colors, int BitsPerComponent, int Columns, uint32_t estimated_size, std::unique_ptr< uint8_t, FxFreeDeleter > *dest_buf, uint32_t *dest_size)
ByteString & operator+=(char ch)
bool operator==(const char *ptr) const
ByteString & operator+=(const char *str)
ByteString & operator=(const char *str)
static WideString FromUTF8(ByteStringView str)
static WideString FromUTF16BE(pdfium::span< const uint8_t > data)
static WideString FromUTF16LE(pdfium::span< const uint8_t > data)
static size_t StripLanguageCodes(pdfium::span< wchar_t > s, size_t n)
const uint16_t kPDFDocEncoding[256]
ByteString PDF_EncodeString(ByteStringView src)
ByteString PDF_EncodeText(WideStringView str)
bool ValidateDecoderPipeline(const CPDF_Array *pDecoders)
uint32_t HexDecode(pdfium::span< const uint8_t > src_span, std::unique_ptr< uint8_t, FxFreeDeleter > *dest_buf, uint32_t *dest_size)
WideString PDF_DecodeText(pdfium::span< const uint8_t > span)
std::unique_ptr< fxcodec::ScanlineDecoder > CreateFaxDecoder(pdfium::span< const uint8_t > src_span, int width, int height, const CPDF_Dictionary *pParams)
uint32_t RunLengthDecode(pdfium::span< const uint8_t > src_span, std::unique_ptr< uint8_t, FxFreeDeleter > *dest_buf, uint32_t *dest_size)
uint32_t FlateOrLZWDecode(bool bLZW, pdfium::span< const uint8_t > src_span, const CPDF_Dictionary *pParams, uint32_t estimated_size, std::unique_ptr< uint8_t, FxFreeDeleter > *dest_buf, uint32_t *dest_size)
ByteString PDF_HexEncodeString(ByteStringView src)
std::unique_ptr< fxcodec::ScanlineDecoder > CreateFlateDecoder(pdfium::span< const uint8_t > src_span, int width, int height, int nComps, int bpc, const CPDF_Dictionary *pParams)
bool PDF_DataDecode(pdfium::span< const uint8_t > src_span, uint32_t estimated_size, bool bImageAcc, const DecoderArray &decoder_array, std::unique_ptr< uint8_t, FxFreeDeleter > *dest_buf, uint32_t *dest_size, ByteString *ImageEncoding, RetainPtr< const CPDF_Dictionary > *pImageParams)
uint32_t A85Decode(pdfium::span< const uint8_t > src_span, std::unique_ptr< uint8_t, FxFreeDeleter > *dest_buf, uint32_t *dest_size)
absl::optional< DecoderArray > GetDecoderArray(RetainPtr< const CPDF_Dictionary > pDict)
bool PDFCharIsLineEnding(uint8_t c)
int FXSYS_HexCharToInt(char c)
#define FX_INVALID_OFFSET