19cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien/*
29cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Copyright (C) 2013 The Android Open Source Project
39cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *
49cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Licensed under the Apache License, Version 2.0 (the "License");
59cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * you may not use this file except in compliance with the License.
69cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * You may obtain a copy of the License at
79cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *
89cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *      http://www.apache.org/licenses/LICENSE-2.0
99cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *
109cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Unless required by applicable law or agreed to in writing, software
119cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * distributed under the License is distributed on an "AS IS" BASIS,
129cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * See the License for the specific language governing permissions and
149cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * limitations under the License.
159cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien */
169cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
179cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien// Determine coverage of font given its raw "cmap" OpenType table
189cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
195f11abd31fa8cfa723f54bd1c98ce4e27e7d3c77Raph Levien#define LOG_TAG "Minikin"
209cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
21722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka#include <algorithm>
229cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include <vector>
239cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienusing std::vector;
249cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
25555d84c6f98eafcbe677cdcb8e9605760acd8ce5Mark Salyzyn#include <log/log.h>
26555d84c6f98eafcbe677cdcb8e9605760acd8ce5Mark Salyzyn
279cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include <minikin/SparseBitSet.h>
289cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include <minikin/CmapCoverage.h>
29818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka#include "MinikinInternal.h"
309cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
31722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka#include <MinikinInternal.h>
32722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
3314e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonakanamespace minikin {
349cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
35722841005f805a5023fd7edefc4016968d1fae10Seigo Nonakaconstexpr uint32_t U32MAX = std::numeric_limits<uint32_t>::max();
36722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
379cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien// These could perhaps be optimized to use __builtin_bswap16 and friends.
389cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienstatic uint32_t readU16(const uint8_t* data, size_t offset) {
396299a6ba13906c695f7a4f6748f7bc5856a110e5Raph Levien    return ((uint32_t)data[offset]) << 8 | ((uint32_t)data[offset + 1]);
409cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
419cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
42722841005f805a5023fd7edefc4016968d1fae10Seigo Nonakastatic uint32_t readU24(const uint8_t* data, size_t offset) {
43722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    return ((uint32_t)data[offset]) << 16 | ((uint32_t)data[offset + 1]) << 8 |
44722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        ((uint32_t)data[offset + 2]);
45722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka}
46722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
479cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienstatic uint32_t readU32(const uint8_t* data, size_t offset) {
486299a6ba13906c695f7a4f6748f7bc5856a110e5Raph Levien    return ((uint32_t)data[offset]) << 24 | ((uint32_t)data[offset + 1]) << 16 |
496299a6ba13906c695f7a4f6748f7bc5856a110e5Raph Levien        ((uint32_t)data[offset + 2]) << 8 | ((uint32_t)data[offset + 3]);
509cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
519cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
520c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka// The start must be larger than or equal to coverage.back() if coverage is not empty.
530c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka// Returns true if the range is appended. Otherwise returns false as an error.
540c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonakastatic bool addRange(vector<uint32_t> &coverage, uint32_t start, uint32_t end) {
555f11abd31fa8cfa723f54bd1c98ce4e27e7d3c77Raph Levien#ifdef VERBOSE_DEBUG
565f11abd31fa8cfa723f54bd1c98ce4e27e7d3c77Raph Levien    ALOGD("adding range %d-%d\n", start, end);
579cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#endif
589cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    if (coverage.empty() || coverage.back() < start) {
599cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        coverage.push_back(start);
609cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        coverage.push_back(end);
610c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka        return true;
620c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka    } else if (coverage.back() == start) {
639cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        coverage.back() = end;
640c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka        return true;
650c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka    } else {
660c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka        // Reject unordered range input since SparseBitSet assumes that the given range vector is
670c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka        // sorted. OpenType specification says cmap entries are sorted in order of code point
680c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka        // values, thus for OpenType compliant font files, we don't reach here.
690c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka        android_errorWriteLog(0x534e4554, "32178311");
700c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka        return false;
719cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
729cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
739cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
74722841005f805a5023fd7edefc4016968d1fae10Seigo Nonakastruct Range {
75722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    uint32_t start;  // inclusive
76722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    uint32_t end;  // exclusive
77722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
78722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    static Range InvalidRange() {
79722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        return Range({ U32MAX, U32MAX });
80722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    }
81722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
82722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    inline bool isValid() const {
83722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        return start != U32MAX && end != U32MAX;
84722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    }
85722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
86722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    // Returns true if left and right intersect.
87722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    inline static bool intersects(const Range& left, const Range& right) {
88722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        return left.isValid() && right.isValid() &&
89722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                left.start < right.end && right.start < left.end;
90722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    }
91722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
92722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    // Returns merged range. This method assumes left and right are not invalid ranges and they have
93722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    // an intersection.
94722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    static Range merge(const Range& left, const Range& right) {
95722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        return Range({ std::min(left.start, right.start), std::max(left.end, right.end) });
96722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    }
97722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka};
98722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
99722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka// Returns Range from given ranges vector. Returns InvalidRange if i is out of range.
100722841005f805a5023fd7edefc4016968d1fae10Seigo Nonakastatic inline Range getRange(const std::vector<uint32_t>& r, size_t i) {
101722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    return i + 1 < r.size() ? Range({ r[i], r[i + 1] }) : Range::InvalidRange();
102722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka}
103722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
104722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka// Merge two sorted lists of ranges into one sorted list.
105722841005f805a5023fd7edefc4016968d1fae10Seigo Nonakastatic std::vector<uint32_t> mergeRanges(
106722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const std::vector<uint32_t>& lRanges, const std::vector<uint32_t>& rRanges) {
107722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    std::vector<uint32_t> out;
108722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
109722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    const size_t lsize = lRanges.size();
110722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    const size_t rsize = rRanges.size();
111722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    out.reserve(lsize + rsize);
112722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    size_t ri = 0;
113722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    size_t li = 0;
114722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    while (li < lsize || ri < rsize) {
115722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        Range left = getRange(lRanges, li);
116722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        Range right = getRange(rRanges, ri);
117722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
118722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        if (!right.isValid()) {
119722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            // No ranges left in rRanges. Just put all remaining ranges in lRanges.
120722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            do {
121722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                Range r = getRange(lRanges, li);
1220c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                addRange(out, r.start, r.end);  // Input is sorted. Never returns false.
123722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                li += 2;
124722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            } while (li < lsize);
125722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            break;
126722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        } else if (!left.isValid()) {
127722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            // No ranges left in lRanges. Just put all remaining ranges in rRanges.
128722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            do {
129722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                Range r = getRange(rRanges, ri);
1300c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                addRange(out, r.start, r.end);  // Input is sorted. Never returns false.
131722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                ri += 2;
132722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            } while (ri < rsize);
133722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            break;
134722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        } else if (!Range::intersects(left, right)) {
135722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            // No intersection. Add smaller range.
136722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            if (left.start < right.start) {
1370c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                addRange(out, left.start, left.end);  // Input is sorted. Never returns false.
138722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                li += 2;
139722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            } else {
1400c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                addRange(out, right.start, right.end);  // Input is sorted. Never returns false.
141722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                ri += 2;
142722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            }
143722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        } else {
144722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            Range merged = Range::merge(left, right);
145722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            li += 2;
146722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            ri += 2;
147722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            left = getRange(lRanges, li);
148722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            right = getRange(rRanges, ri);
149722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            while (Range::intersects(merged, left) || Range::intersects(merged, right)) {
150722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                if (Range::intersects(merged, left)) {
151722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                    merged = Range::merge(merged, left);
152722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                    li += 2;
153722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                    left = getRange(lRanges, li);
154722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                } else {
155722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                    merged = Range::merge(merged, right);
156722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                    ri += 2;
157722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                    right = getRange(rRanges, ri);
158722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                }
159722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            }
1600c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka            addRange(out, merged.start, merged.end);  // Input is sorted. Never returns false.
161722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        }
162722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    }
163722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
164722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    return out;
165722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka}
166722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
167ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien// Get the coverage information out of a Format 4 subtable, storing it in the coverage vector
1689cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienstatic bool getCoverageFormat4(vector<uint32_t>& coverage, const uint8_t* data, size_t size) {
1699cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kSegCountOffset = 6;
1709cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kEndCountOffset = 14;
1719cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kHeaderSize = 16;
1729cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kSegmentSize = 8;  // total size of array elements for one segment
1739cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    if (kEndCountOffset > size) {
1749cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        return false;
1759cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
1769cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    size_t segCount = readU16(data, kSegCountOffset) >> 1;
1779cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    if (kHeaderSize + segCount * kSegmentSize > size) {
1789cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        return false;
1799cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
1809cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    for (size_t i = 0; i < segCount; i++) {
181ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien        uint32_t end = readU16(data, kEndCountOffset + 2 * i);
182ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien        uint32_t start = readU16(data, kHeaderSize + 2 * (segCount + i));
183ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien        if (end < start) {
184ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien            // invalid segment range: size must be positive
185734f037130e14b3d44bc74026d3d065c025a8280Raph Levien            android_errorWriteLog(0x534e4554, "26413177");
186ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien            return false;
187ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien        }
188ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien        uint32_t rangeOffset = readU16(data, kHeaderSize + 2 * (3 * segCount + i));
1899cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        if (rangeOffset == 0) {
190ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien            uint32_t delta = readU16(data, kHeaderSize + 2 * (2 * segCount + i));
1919cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien            if (((end + delta) & 0xffff) > end - start) {
1920c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                if (!addRange(coverage, start, end + 1)) {
1930c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                    return false;
1940c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                }
1959cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien            } else {
196ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien                for (uint32_t j = start; j < end + 1; j++) {
1979cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                    if (((j + delta) & 0xffff) != 0) {
1980c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                        if (!addRange(coverage, j, j + 1)) {
1990c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                            return false;
2000c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                        }
2019cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                    }
2029cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                }
2039cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien            }
2049cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        } else {
205ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien            for (uint32_t j = start; j < end + 1; j++) {
2069cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                uint32_t actualRangeOffset = kHeaderSize + 6 * segCount + rangeOffset +
2079cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                    (i + j - start) * 2;
2089cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                if (actualRangeOffset + 2 > size) {
2095f11abd31fa8cfa723f54bd1c98ce4e27e7d3c77Raph Levien                    // invalid rangeOffset is considered a "warning" by OpenType Sanitizer
2105f11abd31fa8cfa723f54bd1c98ce4e27e7d3c77Raph Levien                    continue;
2119cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                }
212ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien                uint32_t glyphId = readU16(data, actualRangeOffset);
2139cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                if (glyphId != 0) {
2140c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                    if (!addRange(coverage, j, j + 1)) {
2150c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                        return false;
2160c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                    }
2179cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                }
2189cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien            }
2199cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        }
2209cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
2219cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    return true;
2229cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
2239cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
2249cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien// Get the coverage information out of a Format 12 subtable, storing it in the coverage vector
2259cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienstatic bool getCoverageFormat12(vector<uint32_t>& coverage, const uint8_t* data, size_t size) {
2269cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kNGroupsOffset = 12;
2279cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kFirstGroupOffset = 16;
2289cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kGroupSize = 12;
2299cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kStartCharCodeOffset = 0;
2309cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kEndCharCodeOffset = 4;
2316299a6ba13906c695f7a4f6748f7bc5856a110e5Raph Levien    const size_t kMaxNGroups = 0xfffffff0 / kGroupSize;  // protection against overflow
2326299a6ba13906c695f7a4f6748f7bc5856a110e5Raph Levien    // For all values < kMaxNGroups, kFirstGroupOffset + nGroups * kGroupSize fits in 32 bits.
2339cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    if (kFirstGroupOffset > size) {
2349cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        return false;
2359cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
2369cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    uint32_t nGroups = readU32(data, kNGroupsOffset);
2376299a6ba13906c695f7a4f6748f7bc5856a110e5Raph Levien    if (nGroups >= kMaxNGroups || kFirstGroupOffset + nGroups * kGroupSize > size) {
238734f037130e14b3d44bc74026d3d065c025a8280Raph Levien        android_errorWriteLog(0x534e4554, "25645298");
2399cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        return false;
2409cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
2419cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    for (uint32_t i = 0; i < nGroups; i++) {
2429cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        uint32_t groupOffset = kFirstGroupOffset + i * kGroupSize;
2439cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        uint32_t start = readU32(data, groupOffset + kStartCharCodeOffset);
2449cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        uint32_t end = readU32(data, groupOffset + kEndCharCodeOffset);
245ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien        if (end < start) {
246ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien            // invalid group range: size must be positive
247734f037130e14b3d44bc74026d3d065c025a8280Raph Levien            android_errorWriteLog(0x534e4554, "26413177");
248ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien            return false;
249ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien        }
250818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka
251818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka        // No need to read outside of Unicode code point range.
252818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka        if (start > MAX_UNICODE_CODE_POINT) {
253818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka            return true;
254818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka        }
255818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka        if (end > MAX_UNICODE_CODE_POINT) {
256818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka            // file is inclusive, vector is exclusive
257373b1809aefb1f64278e6bf01c544bbc3f9e93c7Seigo Nonaka            if (end == 0xFFFFFFFF) {
258373b1809aefb1f64278e6bf01c544bbc3f9e93c7Seigo Nonaka                android_errorWriteLog(0x534e4554, "62134807");
259373b1809aefb1f64278e6bf01c544bbc3f9e93c7Seigo Nonaka            }
2600c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka            return addRange(coverage, start, MAX_UNICODE_CODE_POINT + 1);
2610c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka        }
2620c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka        if (!addRange(coverage, start, end + 1)) {  // file is inclusive, vector is exclusive
2630c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka            return false;
264818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka        }
2659cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
2669cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    return true;
2679cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
2689cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
269db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka// Lower value has higher priority. 0 for the highest priority table.
270db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka// kLowestPriority for unsupported tables.
271db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka// This order comes from HarfBuzz's hb-ot-font.cc and needs to be kept in sync with it.
272db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonakaconstexpr uint8_t kLowestPriority = 255;
273db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonakauint8_t getTablePriority(uint16_t platformId, uint16_t encodingId) {
274db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 3 && encodingId == 10) {
275db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 0;
276db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
277db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 0 && encodingId == 6) {
278db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 1;
279db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
280db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 0 && encodingId == 4) {
281db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 2;
282db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
283db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 3 && encodingId == 1) {
284db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 3;
285db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
286db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 0 && encodingId == 3) {
287db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 4;
288db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
289db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 0 && encodingId == 2) {
290db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 5;
291db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
292db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 0 && encodingId == 1) {
293db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 6;
294db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
295db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 0 && encodingId == 0) {
296db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 7;
297db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
298db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    // Tables other than above are not supported.
299db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    return kLowestPriority;
300db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka}
301db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
302722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka// Get merged coverage information from default UVS Table and non-default UVS Table. Note that this
303722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka// function assumes code points in both default UVS Table and non-default UVS table are stored in
304722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka// ascending order. This is required by the standard.
305722841005f805a5023fd7edefc4016968d1fae10Seigo Nonakastatic bool getVSCoverage(std::vector<uint32_t>* out_ranges, const uint8_t* data, size_t size,
306722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        uint32_t defaultUVSTableOffset, uint32_t nonDefaultUVSTableOffset,
307722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const SparseBitSet& baseCoverage) {
308722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    // Need to merge supported ranges from default UVS Table and non-default UVS Table.
309722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    // First, collect all supported code points from non default UVS table.
310722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    std::vector<uint32_t> rangesFromNonDefaultUVSTable;
311722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    if (nonDefaultUVSTableOffset != 0) {
312722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        constexpr size_t kHeaderSize = 4;
313722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        constexpr size_t kUVSMappingRecordSize = 5;
314722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
315722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const uint8_t* nonDefaultUVSTable = data + nonDefaultUVSTableOffset;
316722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        // This subtraction doesn't underflow since the caller already checked
317722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        // size > nonDefaultUVSTableOffset.
318722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const size_t nonDefaultUVSTableRemaining = size - nonDefaultUVSTableOffset;
319722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        if (nonDefaultUVSTableRemaining < kHeaderSize) {
320722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            return false;
321722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        }
3223056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka        const uint64_t numRecords = readU32(nonDefaultUVSTable, 0);
3233056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka        const uint64_t sizeToRead = numRecords * kUVSMappingRecordSize + kHeaderSize;
3243056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka        if (sizeToRead > nonDefaultUVSTableRemaining) {
3253056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka            if (sizeToRead > UINT_MAX) {
3263056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka                android_errorWriteLog(0x534e4554, "70808908");
3273056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka            }
328722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            return false;
329722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        }
330722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        for (uint32_t i = 0; i < numRecords; ++i) {
331722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            const size_t recordOffset = kHeaderSize + kUVSMappingRecordSize * i;
332722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            const uint32_t codePoint = readU24(nonDefaultUVSTable, recordOffset);
3330c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka            if (!addRange(rangesFromNonDefaultUVSTable, codePoint, codePoint + 1)) {
3340c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                return false;
3350c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka            }
336722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        }
337722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    }
338722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
339722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    // Then, construct range from default UVS Table with merging code points from non default UVS
340722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    // table.
341722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    std::vector<uint32_t> rangesFromDefaultUVSTable;
342722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    if (defaultUVSTableOffset != 0) {
343722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        constexpr size_t kHeaderSize = 4;
344722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        constexpr size_t kUnicodeRangeRecordSize = 4;
345722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
346722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const uint8_t* defaultUVSTable = data + defaultUVSTableOffset;
347722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        // This subtraction doesn't underflow since the caller already checked
348722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        // size > defaultUVSTableOffset.
349722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const size_t defaultUVSTableRemaining = size - defaultUVSTableOffset;
350722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
351722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        if (defaultUVSTableRemaining < kHeaderSize) {
352722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            return false;
353722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        }
3543056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka        const uint64_t numRecords = readU32(defaultUVSTable, 0);
3553056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka        const uint64_t sizeToRead = numRecords * kUnicodeRangeRecordSize + kHeaderSize;
3563056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka        if (sizeToRead > defaultUVSTableRemaining) {
3573056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka            if (sizeToRead > UINT_MAX) {
3583056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka                android_errorWriteLog(0x534e4554, "70808908");
3593056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka            }
360722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            return false;
361722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        }
362722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
363722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        for (uint32_t i = 0; i < numRecords; ++i) {
364722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            const size_t recordOffset = kHeaderSize + kUnicodeRangeRecordSize * i;
365722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            const uint32_t startCp = readU24(defaultUVSTable, recordOffset);
366722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            const uint8_t rangeLength = defaultUVSTable[recordOffset + 3];
367722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
368722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            // Then insert range from default UVS Table, but exclude if the base codepoint is not
369722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            // supported.
370722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            for (uint32_t cp = startCp; cp <= startCp + rangeLength; ++cp) {
371722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                // All codepoints in default UVS table should go to the glyphs of the codepoints
372722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                // without variation selectors. We need to check the default glyph availability and
373722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                // exclude the codepoint if it is not supported by defualt cmap table.
374722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                if (baseCoverage.get(cp)) {
3750c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                    if (!addRange(rangesFromDefaultUVSTable, cp, cp + 1 /* exclusive */)) {
3760c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                        return false;
3770c943b002dfed4c19196a4d162737057f8ed5a56Seigo Nonaka                    }
378722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                }
379722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            }
380722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        }
381722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    }
382722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    *out_ranges = mergeRanges(rangesFromDefaultUVSTable, rangesFromNonDefaultUVSTable);
383722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    return true;
384722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka}
385722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
386722841005f805a5023fd7edefc4016968d1fae10Seigo Nonakastatic void getCoverageFormat14(std::vector<std::unique_ptr<SparseBitSet>>* out,
387722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const uint8_t* data, size_t size, const SparseBitSet& baseCoverage) {
388722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    constexpr size_t kHeaderSize = 10;
389722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    constexpr size_t kRecordSize = 11;
390722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    constexpr size_t kLengthOffset = 2;
391722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    constexpr size_t kNumRecordOffset = 6;
392722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
393722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    out->clear();
394722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    if (size < kHeaderSize) {
395722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        return;
396722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    }
397722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
398722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    const uint32_t length = readU32(data, kLengthOffset);
399722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    if (size < length) {
400722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        return;
401722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    }
402722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
4033056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka    const uint64_t numRecords = readU32(data, kNumRecordOffset);
4043056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka    const uint64_t sizeToRead = kHeaderSize + kRecordSize * numRecords;
4053056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka    if (numRecords == 0 || sizeToRead > length) {
4063056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka        if (sizeToRead > UINT_MAX) {
4073056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka            android_errorWriteLog(0x534e4554, "70808908");
4083056f04d293bd16e56cc72e10edd060b8c1ca0f5Seigo Nonaka        }
409722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        return;
410722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    }
411722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
412722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    for (uint32_t i = 0; i < numRecords; ++i) {
413722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        // Insert from the largest code points since it determines the size of the output vector.
414722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const uint32_t recordHeadOffset = kHeaderSize + kRecordSize * (numRecords - i - 1);
415722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const uint32_t vsCodePoint = readU24(data, recordHeadOffset);
416722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const uint32_t defaultUVSOffset = readU32(data, recordHeadOffset + 3);
417722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const uint32_t nonDefaultUVSOffset = readU32(data, recordHeadOffset + 7);
418722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        if (defaultUVSOffset > length || nonDefaultUVSOffset > length) {
419722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            continue;
420722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        }
421722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
422722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const uint16_t vsIndex = getVsIndex(vsCodePoint);
423722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        if (vsIndex == INVALID_VS_INDEX) {
424722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            continue;
425722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        }
426722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        std::vector<uint32_t> ranges;
427722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        if (!getVSCoverage(&ranges, data, length, defaultUVSOffset, nonDefaultUVSOffset,
428722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                baseCoverage)) {
429722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            continue;
430722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        }
431722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        if (out->size() < vsIndex + 1) {
432722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            out->resize(vsIndex + 1);
433722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        }
434722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        (*out)[vsIndex].reset(new SparseBitSet(ranges.data(), ranges.size() >> 1));
435722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    }
436722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
437722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    out->shrink_to_fit();
438722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka}
439722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
440db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo NonakaSparseBitSet CmapCoverage::getCoverage(const uint8_t* cmap_data, size_t cmap_size,
441722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        std::vector<std::unique_ptr<SparseBitSet>>* out) {
442db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    constexpr size_t kHeaderSize = 4;
443db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    constexpr size_t kNumTablesOffset = 2;
444db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    constexpr size_t kTableSize = 8;
445db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    constexpr size_t kPlatformIdOffset = 0;
446db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    constexpr size_t kEncodingIdOffset = 2;
447db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    constexpr size_t kOffsetOffset = 4;
448db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    constexpr size_t kFormatOffset = 0;
449722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    constexpr uint32_t kNoTable = UINT32_MAX;
450db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
4519cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    if (kHeaderSize > cmap_size) {
452db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return SparseBitSet();
4539cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
454ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien    uint32_t numTables = readU16(cmap_data, kNumTablesOffset);
4559cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    if (kHeaderSize + numTables * kTableSize > cmap_size) {
456db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return SparseBitSet();
4579cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
458db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
459722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    uint32_t bestTableOffset = kNoTable;
460db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    uint16_t bestTableFormat = 0;
461db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    uint8_t bestTablePriority = kLowestPriority;
462722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    uint32_t vsTableOffset = kNoTable;
463db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    for (uint32_t i = 0; i < numTables; ++i) {
464db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        const uint32_t tableHeadOffset = kHeaderSize + i * kTableSize;
465db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        const uint16_t platformId = readU16(cmap_data, tableHeadOffset + kPlatformIdOffset);
466db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        const uint16_t encodingId = readU16(cmap_data, tableHeadOffset + kEncodingIdOffset);
467db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        const uint32_t offset = readU32(cmap_data, tableHeadOffset + kOffsetOffset);
468db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
469db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        if (offset > cmap_size - 2) {
470db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            continue;  // Invalid table: not enough space to read.
471db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        }
472db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        const uint16_t format = readU16(cmap_data, offset + kFormatOffset);
473db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
474db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        if (platformId == 0 /* Unicode */ && encodingId == 5 /* Variation Sequences */) {
475722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            if (vsTableOffset == kNoTable && format == 14) {
476722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka                vsTableOffset = offset;
477db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            } else {
478db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                // Ignore the (0, 5) table if we have already seen another valid one or it's in a
479db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                // format we don't understand.
480db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            }
481db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        } else {
482db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            uint32_t length;
483db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            uint32_t language;
484db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
485db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            if (format == 4) {
486db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                constexpr size_t lengthOffset = 2;
487db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                constexpr size_t languageOffset = 4;
488db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                constexpr size_t minTableSize = languageOffset + 2;
489db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                if (offset > cmap_size - minTableSize) {
490db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                    continue;  // Invalid table: not enough space to read.
491db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                }
492db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                length = readU16(cmap_data, offset + lengthOffset);
493db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                language = readU16(cmap_data, offset + languageOffset);
494db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            } else if (format == 12) {
495db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                constexpr size_t lengthOffset = 4;
496db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                constexpr size_t languageOffset = 8;
497db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                constexpr size_t minTableSize = languageOffset + 4;
498db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                if (offset > cmap_size - minTableSize) {
499db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                    continue;  // Invalid table: not enough space to read.
500db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                }
501db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                length = readU32(cmap_data, offset + lengthOffset);
502db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                language = readU32(cmap_data, offset + languageOffset);
503db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            } else {
504db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                continue;
505db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            }
506db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
507db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            if (length > cmap_size - offset) {
508db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                continue;  // Invalid table: table length is larger than whole cmap data size.
509db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            }
510db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            if (language != 0) {
511db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                // Unsupported or invalid table: this is either a subtable for the Macintosh
512db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                // platform (which we don't support), or an invalid subtable since language field
513db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                // should be zero for non-Macintosh subtables.
514db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                continue;
515db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            }
516db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            const uint8_t priority = getTablePriority(platformId, encodingId);
517db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            if (priority < bestTablePriority) {
518db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                bestTableOffset = offset;
519db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                bestTablePriority = priority;
520db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                bestTableFormat = format;
5216b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka            }
5229cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        }
523722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        if (vsTableOffset != kNoTable && bestTablePriority == 0 /* highest priority */) {
524db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            // Already found the highest priority table and variation sequences table. No need to
525db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            // look at remaining tables.
526db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            break;
527db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        }
5289cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
529722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
530722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    SparseBitSet coverage;
531722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
532722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    if (bestTableOffset != kNoTable) {
533722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const uint8_t* tableData = cmap_data + bestTableOffset;
534722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const size_t tableSize = cmap_size - bestTableOffset;
535722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        bool success;
536722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        vector<uint32_t> coverageVec;
537722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        if (bestTableFormat == 4) {
538722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            success = getCoverageFormat4(coverageVec, tableData, tableSize);
539722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        } else {
540722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            success = getCoverageFormat12(coverageVec, tableData, tableSize);
541722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        }
542722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka
543722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        if (success) {
544722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka            coverage = SparseBitSet(&coverageVec.front(), coverageVec.size() >> 1);
545722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        }
5469cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
547db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
548722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    if (vsTableOffset != kNoTable) {
549722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const uint8_t* tableData = cmap_data + vsTableOffset;
550722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        const size_t tableSize = cmap_size - vsTableOffset;
551722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka        getCoverageFormat14(out, tableData, tableSize, coverage);
552722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    }
553722841005f805a5023fd7edefc4016968d1fae10Seigo Nonaka    return coverage;
5549cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
5559cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
55614e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonaka}  // namespace minikin
557