Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
85.71% covered (warning)
85.71%
12 / 14
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
BidiResult
85.71% covered (warning)
85.71%
12 / 14
50.00% covered (danger)
50.00%
1 / 2
6.10
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 charLevelAt
84.62% covered (warning)
84.62%
11 / 13
0.00% covered (danger)
0.00%
0 / 1
5.09
1<?php
2
3declare(strict_types=1);
4
5namespace Phpdftk\Text;
6
7/**
8 * Output of {@see Bidi::analyze}. Stores the runs in logical (source) order
9 * and exposes `charLevelAt` for callers that need a per-character level
10 * (e.g. shaping a run that spans multiple levels).
11 */
12final readonly class BidiResult
13{
14    /** @param list<BidiRun> $runs in logical / source order */
15    public function __construct(
16        public BidiBase $resolvedBase,
17        public array $runs,
18    ) {}
19
20    /**
21     * Resolved bidi level for a single byte offset. Returns null if the
22     * offset is outside any run (typically because it's at or past the end
23     * of the input).
24     *
25     * Binary searches `runs` — O(log n).
26     */
27    public function charLevelAt(int $offset): ?int
28    {
29        if ($this->runs === []) {
30            return null;
31        }
32        $lo = 0;
33        $hi = count($this->runs) - 1;
34        while ($lo <= $hi) {
35            $mid = intdiv($lo + $hi, 2);
36            $run = $this->runs[$mid];
37            if ($offset < $run->offset) {
38                $hi = $mid - 1;
39            } elseif ($offset >= $run->offset + $run->length) {
40                $lo = $mid + 1;
41            } else {
42                return $run->level;
43            }
44        }
45        return null;
46    }
47}