Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
47 / 47
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
Cmap
100.00% covered (success)
100.00%
47 / 47
100.00% covered (success)
100.00%
2 / 2
15
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 parseSubTables
100.00% covered (success)
100.00%
40 / 40
100.00% covered (success)
100.00%
1 / 1
14
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <nick@popphp.org>
8 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Pdf\Build\Font\TrueType\Table;
16
17use Pop\Pdf\Build\Font;
18
19use Pop\Utils\ArrayObject as Data;
20
21/**
22 * CMAP table class
23 *
24 * @category   Pop
25 * @package    Pop\Pdf
26 * @author     Nick Sagona, III <nick@popphp.org>
27 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
28 * @license    https://www.popphp.org/license     New BSD License
29 * @version    6.0.0
30 */
31class Cmap extends AbstractTable
32{
33
34    /**
35     * Font table properties
36     * @var array
37     */
38    protected array $properties = [
39        'header'    => null,
40        'subTables' => []
41    ];
42
43    /**
44     * Constructor
45     *
46     * Instantiate a TTF 'cmap' table object.
47     *
48     * @param  Font\TrueType $font
49     */
50    public function __construct(Font\TrueType $font)
51    {
52        $bytePos = $font->tableInfo['cmap']->offset;
53
54        // Get the CMAP header data.
55        $cmapTableHeader = unpack(
56            'ntableVersion/' .
57            'nnumberOfTables', $font->read($bytePos, 4)
58        );
59
60        $this->properties['header'] = new Data($cmapTableHeader);
61        $this->parseSubTables($font);
62    }
63
64    /**
65     * Method to parse the CMAP sub-tables.
66     *
67     * @param  \Pop\Pdf\Build\Font\TrueType $font
68     * @return void
69     */
70    protected function parseSubTables(\Pop\Pdf\Build\Font\TrueType $font): void
71    {
72        $bytePos = $font->tableInfo['cmap']->offset + 4;
73
74        // Get each of the sub-table's data.
75        for ($i = 0; $i < $this->properties['header']->numberOfTables; $i++) {
76            $ary = unpack(
77                'nplatformId/' .
78                'nencodingId/' .
79                'Noffset', $font->read($bytePos, 8)
80            );
81            if (($ary['platformId'] == 0) && ($ary['encodingId'] == 0)) {
82                $ary['encoding'] = 'Unicode 2.0';
83            } else if (($ary['platformId'] == 0) && ($ary['encodingId'] == 3)) {
84                $ary['encoding'] = 'Unicode';
85            } else if (($ary['platformId'] == 3) && ($ary['encodingId'] == 1)) {
86                $ary['encoding'] = 'Microsoft Unicode';
87            } else if (($ary['platformId'] == 1) && ($ary['encodingId'] == 0)) {
88                $ary['encoding'] = 'Mac Roman';
89            } else {
90                $ary['encoding'] = 'Unknown';
91            }
92            $this->properties['subTables'][] = new Data($ary);
93            $bytePos += 8;
94        }
95
96        // Parse each of the sub-table's data.
97        foreach ($this->properties['subTables'] as $key => $subTable) {
98            $bytePos = $font->tableInfo['cmap']->offset + $subTable->offset;
99            $ary = unpack(
100                'nformat/' .
101                'nlength/' .
102                'nlanguage', $font->read($bytePos, 6)
103            );
104            $this->properties['subTables'][$key]->format = $ary['format'];
105            $this->properties['subTables'][$key]->length = $ary['length'];
106            $this->properties['subTables'][$key]->language = $ary['language'];
107            $bytePos += 6;
108            $this->properties['subTables'][$key]->data = $font->read($bytePos, $ary['length'] - 6);
109            switch ($this->properties['subTables'][$key]->format) {
110                case 0:
111                    $this->properties['subTables'][$key]->parsed = Cmap\ByteEncoding::parseData($this->properties['subTables'][$key]->data);
112                    break;
113                case 4:
114                    $this->properties['subTables'][$key]->parsed = Cmap\SegmentToDelta::parseData($this->properties['subTables'][$key]->data);
115                    break;
116                case 6:
117                    $this->properties['subTables'][$key]->parsed = Cmap\TrimmedTable::parseData($this->properties['subTables'][$key]->data);
118                    break;
119            }
120        }
121    }
122
123}