summaryrefslogtreecommitdiffstats
path: root/vendor/setasign/fpdi/src/PdfParser/Type/PdfDictionary.php
blob: 281884245944745d9677df8fb4f46e8f642edc5d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<?php

/**
 * This file is part of FPDI
 *
 * @package   setasign\Fpdi
 * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
 * @license   http://opensource.org/licenses/mit-license The MIT License
 */

namespace setasign\Fpdi\PdfParser\Type;

use setasign\Fpdi\PdfParser\PdfParser;
use setasign\Fpdi\PdfParser\StreamReader;
use setasign\Fpdi\PdfParser\Tokenizer;

/**
 * Class representing a PDF dictionary object
 */
class PdfDictionary extends PdfType
{
    /**
     * Parses a dictionary of the passed tokenizer, stream-reader and parser.
     *
     * @param Tokenizer $tokenizer
     * @param StreamReader $streamReader
     * @param PdfParser $parser
     * @return bool|self
     * @throws PdfTypeException
     */
    public static function parse(Tokenizer $tokenizer, StreamReader $streamReader, PdfParser $parser)
    {
        $entries = [];

        while (true) {
            $token = $tokenizer->getNextToken();
            if ($token === '>' && $streamReader->getByte() === '>') {
                $streamReader->addOffset(1);
                break;
            }

            $key = $parser->readValue($token);
            if ($key === false) {
                return false;
            }

            // ensure the first value to be a Name object
            if (!($key instanceof PdfName)) {
                $lastToken = null;
                // ignore all other entries and search for the closing brackets
                while (($token = $tokenizer->getNextToken()) !== '>' && $token !== false && $lastToken !== '>') {
                    $lastToken = $token;
                }

                if ($token === false) {
                    return false;
                }

                break;
            }


            $value = $parser->readValue();
            if ($value === false) {
                return false;
            }

            if ($value instanceof PdfNull) {
                continue;
            }

            // catch missing value
            if ($value instanceof PdfToken && $value->value === '>' && $streamReader->getByte() === '>') {
                $streamReader->addOffset(1);
                break;
            }

            $entries[$key->value] = $value;
        }

        $v = new self();
        $v->value = $entries;

        return $v;
    }

    /**
     * Helper method to create an instance.
     *
     * @param PdfType[] $entries The keys are the name entries of the dictionary.
     * @return self
     */
    public static function create(array $entries = [])
    {
        $v = new self();
        $v->value = $entries;

        return $v;
    }

    /**
     * Get a value by its key from a dictionary or a default value.
     *
     * @param mixed $dictionary
     * @param string $key
     * @param PdfType|null $default
     * @return PdfNull|PdfType
     * @throws PdfTypeException
     */
    public static function get($dictionary, $key, PdfType $default = null)
    {
        $dictionary = self::ensure($dictionary);

        if (isset($dictionary->value[$key])) {
            return $dictionary->value[$key];
        }

        return $default === null
            ? new PdfNull()
            : $default;
    }

    /**
     * Ensures that the passed value is a PdfDictionary instance.
     *
     * @param mixed $dictionary
     * @return self
     * @throws PdfTypeException
     */
    public static function ensure($dictionary)
    {
        return PdfType::ensureType(self::class, $dictionary, 'Dictionary value expected.');
    }
}