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
219196194d76e4325c5bb0c23f22a5787a717067edSeigo 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
319196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka#include <MinikinInternal.h>
329196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
3314e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonakanamespace minikin {
349cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
359196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonakaconstexpr uint32_t U32MAX = std::numeric_limits<uint32_t>::max();
369196194d76e4325c5bb0c23f22a5787a717067edSeigo 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
429196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonakastatic uint32_t readU24(const uint8_t* data, size_t offset) {
439196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    return ((uint32_t)data[offset]) << 16 | ((uint32_t)data[offset + 1]) << 8 |
449196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        ((uint32_t)data[offset + 2]);
459196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka}
469196194d76e4325c5bb0c23f22a5787a717067edSeigo 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
529cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienstatic void addRange(vector<uint32_t> &coverage, uint32_t start, uint32_t end) {
535f11abd31fa8cfa723f54bd1c98ce4e27e7d3c77Raph Levien#ifdef VERBOSE_DEBUG
545f11abd31fa8cfa723f54bd1c98ce4e27e7d3c77Raph Levien    ALOGD("adding range %d-%d\n", start, end);
559cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#endif
569cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    if (coverage.empty() || coverage.back() < start) {
579cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        coverage.push_back(start);
589cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        coverage.push_back(end);
599cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    } else {
609cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        coverage.back() = end;
619cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
629cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
639cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
649196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonakastruct Range {
659196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    uint32_t start;  // inclusive
669196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    uint32_t end;  // exclusive
679196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
689196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    static Range InvalidRange() {
699196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        return Range({ U32MAX, U32MAX });
709196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    }
719196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
729196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    inline bool isValid() const {
739196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        return start != U32MAX && end != U32MAX;
749196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    }
759196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
769196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    // Returns true if left and right intersect.
779196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    inline static bool intersects(const Range& left, const Range& right) {
789196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        return left.isValid() && right.isValid() &&
799196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                left.start < right.end && right.start < left.end;
809196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    }
819196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
829196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    // Returns merged range. This method assumes left and right are not invalid ranges and they have
839196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    // an intersection.
849196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    static Range merge(const Range& left, const Range& right) {
859196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        return Range({ std::min(left.start, right.start), std::max(left.end, right.end) });
869196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    }
879196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka};
889196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
899196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka// Returns Range from given ranges vector. Returns InvalidRange if i is out of range.
909196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonakastatic inline Range getRange(const std::vector<uint32_t>& r, size_t i) {
919196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    return i + 1 < r.size() ? Range({ r[i], r[i + 1] }) : Range::InvalidRange();
929196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka}
939196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
949196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka// Merge two sorted lists of ranges into one sorted list.
959196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonakastatic std::vector<uint32_t> mergeRanges(
969196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const std::vector<uint32_t>& lRanges, const std::vector<uint32_t>& rRanges) {
979196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    std::vector<uint32_t> out;
989196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
999196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    const size_t lsize = lRanges.size();
1009196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    const size_t rsize = rRanges.size();
1019196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    out.reserve(lsize + rsize);
1029196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    size_t ri = 0;
1039196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    size_t li = 0;
1049196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    while (li < lsize || ri < rsize) {
1059196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        Range left = getRange(lRanges, li);
1069196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        Range right = getRange(rRanges, ri);
1079196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
1089196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        if (!right.isValid()) {
1099196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            // No ranges left in rRanges. Just put all remaining ranges in lRanges.
1109196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            do {
1119196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                Range r = getRange(lRanges, li);
1129196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                addRange(out, r.start, r.end);
1139196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                li += 2;
1149196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            } while (li < lsize);
1159196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            break;
1169196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        } else if (!left.isValid()) {
1179196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            // No ranges left in lRanges. Just put all remaining ranges in rRanges.
1189196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            do {
1199196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                Range r = getRange(rRanges, ri);
1209196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                addRange(out, r.start, r.end);
1219196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                ri += 2;
1229196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            } while (ri < rsize);
1239196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            break;
1249196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        } else if (!Range::intersects(left, right)) {
1259196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            // No intersection. Add smaller range.
1269196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            if (left.start < right.start) {
1279196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                addRange(out, left.start, left.end);
1289196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                li += 2;
1299196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            } else {
1309196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                addRange(out, right.start, right.end);
1319196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                ri += 2;
1329196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            }
1339196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        } else {
1349196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            Range merged = Range::merge(left, right);
1359196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            li += 2;
1369196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            ri += 2;
1379196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            left = getRange(lRanges, li);
1389196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            right = getRange(rRanges, ri);
1399196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            while (Range::intersects(merged, left) || Range::intersects(merged, right)) {
1409196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                if (Range::intersects(merged, left)) {
1419196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                    merged = Range::merge(merged, left);
1429196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                    li += 2;
1439196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                    left = getRange(lRanges, li);
1449196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                } else {
1459196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                    merged = Range::merge(merged, right);
1469196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                    ri += 2;
1479196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                    right = getRange(rRanges, ri);
1489196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                }
1499196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            }
1509196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            addRange(out, merged.start, merged.end);
1519196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        }
1529196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    }
1539196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
1549196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    return out;
1559196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka}
1569196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
157ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien// Get the coverage information out of a Format 4 subtable, storing it in the coverage vector
1589cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienstatic bool getCoverageFormat4(vector<uint32_t>& coverage, const uint8_t* data, size_t size) {
1599cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kSegCountOffset = 6;
1609cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kEndCountOffset = 14;
1619cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kHeaderSize = 16;
1629cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kSegmentSize = 8;  // total size of array elements for one segment
1639cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    if (kEndCountOffset > size) {
1649cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        return false;
1659cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
1669cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    size_t segCount = readU16(data, kSegCountOffset) >> 1;
1679cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    if (kHeaderSize + segCount * kSegmentSize > size) {
1689cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        return false;
1699cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
1709cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    for (size_t i = 0; i < segCount; i++) {
171ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien        uint32_t end = readU16(data, kEndCountOffset + 2 * i);
172ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien        uint32_t start = readU16(data, kHeaderSize + 2 * (segCount + i));
173ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien        if (end < start) {
174ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien            // invalid segment range: size must be positive
175734f037130e14b3d44bc74026d3d065c025a8280Raph Levien            android_errorWriteLog(0x534e4554, "26413177");
176ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien            return false;
177ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien        }
178ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien        uint32_t rangeOffset = readU16(data, kHeaderSize + 2 * (3 * segCount + i));
1799cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        if (rangeOffset == 0) {
180ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien            uint32_t delta = readU16(data, kHeaderSize + 2 * (2 * segCount + i));
1819cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien            if (((end + delta) & 0xffff) > end - start) {
1829cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                addRange(coverage, start, end + 1);
1839cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien            } else {
184ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien                for (uint32_t j = start; j < end + 1; j++) {
1859cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                    if (((j + delta) & 0xffff) != 0) {
1869cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                        addRange(coverage, j, j + 1);
1879cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                    }
1889cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                }
1899cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien            }
1909cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        } else {
191ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien            for (uint32_t j = start; j < end + 1; j++) {
1929cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                uint32_t actualRangeOffset = kHeaderSize + 6 * segCount + rangeOffset +
1939cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                    (i + j - start) * 2;
1949cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                if (actualRangeOffset + 2 > size) {
1955f11abd31fa8cfa723f54bd1c98ce4e27e7d3c77Raph Levien                    // invalid rangeOffset is considered a "warning" by OpenType Sanitizer
1965f11abd31fa8cfa723f54bd1c98ce4e27e7d3c77Raph Levien                    continue;
1979cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                }
198ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien                uint32_t glyphId = readU16(data, actualRangeOffset);
1999cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                if (glyphId != 0) {
2009cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                    addRange(coverage, j, j + 1);
2019cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                }
2029cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien            }
2039cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        }
2049cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
2059cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    return true;
2069cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
2079cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
2089cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien// Get the coverage information out of a Format 12 subtable, storing it in the coverage vector
2099cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienstatic bool getCoverageFormat12(vector<uint32_t>& coverage, const uint8_t* data, size_t size) {
2109cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kNGroupsOffset = 12;
2119cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kFirstGroupOffset = 16;
2129cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kGroupSize = 12;
2139cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kStartCharCodeOffset = 0;
2149cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const size_t kEndCharCodeOffset = 4;
2156299a6ba13906c695f7a4f6748f7bc5856a110e5Raph Levien    const size_t kMaxNGroups = 0xfffffff0 / kGroupSize;  // protection against overflow
2166299a6ba13906c695f7a4f6748f7bc5856a110e5Raph Levien    // For all values < kMaxNGroups, kFirstGroupOffset + nGroups * kGroupSize fits in 32 bits.
2179cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    if (kFirstGroupOffset > size) {
2189cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        return false;
2199cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
2209cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    uint32_t nGroups = readU32(data, kNGroupsOffset);
2216299a6ba13906c695f7a4f6748f7bc5856a110e5Raph Levien    if (nGroups >= kMaxNGroups || kFirstGroupOffset + nGroups * kGroupSize > size) {
222734f037130e14b3d44bc74026d3d065c025a8280Raph Levien        android_errorWriteLog(0x534e4554, "25645298");
2239cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        return false;
2249cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
2259cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    for (uint32_t i = 0; i < nGroups; i++) {
2269cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        uint32_t groupOffset = kFirstGroupOffset + i * kGroupSize;
2279cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        uint32_t start = readU32(data, groupOffset + kStartCharCodeOffset);
2289cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        uint32_t end = readU32(data, groupOffset + kEndCharCodeOffset);
229ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien        if (end < start) {
230ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien            // invalid group range: size must be positive
231734f037130e14b3d44bc74026d3d065c025a8280Raph Levien            android_errorWriteLog(0x534e4554, "26413177");
232ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien            return false;
233ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien        }
234818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka
235818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka        // No need to read outside of Unicode code point range.
236818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka        if (start > MAX_UNICODE_CODE_POINT) {
237818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka            return true;
238818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka        }
239818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka        if (end > MAX_UNICODE_CODE_POINT) {
240818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka            // file is inclusive, vector is exclusive
241818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka            addRange(coverage, start, MAX_UNICODE_CODE_POINT + 1);
242818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka            return true;
243818fbee83a72ca86f64527eb90b2f15ec9b28504Seigo Nonaka        }
2449cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        addRange(coverage, start, end + 1);  // file is inclusive, vector is exclusive
2459cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
2469cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    return true;
2479cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
2489cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
249db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka// Lower value has higher priority. 0 for the highest priority table.
250db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka// kLowestPriority for unsupported tables.
251db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka// This order comes from HarfBuzz's hb-ot-font.cc and needs to be kept in sync with it.
252db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonakaconstexpr uint8_t kLowestPriority = 255;
253db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonakauint8_t getTablePriority(uint16_t platformId, uint16_t encodingId) {
254db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 3 && encodingId == 10) {
255db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 0;
256db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
257db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 0 && encodingId == 6) {
258db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 1;
259db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
260db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 0 && encodingId == 4) {
261db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 2;
262db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
263db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 3 && encodingId == 1) {
264db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 3;
265db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
266db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 0 && encodingId == 3) {
267db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 4;
268db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
269db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 0 && encodingId == 2) {
270db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 5;
271db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
272db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 0 && encodingId == 1) {
273db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 6;
274db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
275db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    if (platformId == 0 && encodingId == 0) {
276db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return 7;
277db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    }
278db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    // Tables other than above are not supported.
279db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    return kLowestPriority;
280db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka}
281db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
2829196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka// Get merged coverage information from default UVS Table and non-default UVS Table. Note that this
2839196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka// function assumes code points in both default UVS Table and non-default UVS table are stored in
2849196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka// ascending order. This is required by the standard.
2859196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonakastatic bool getVSCoverage(std::vector<uint32_t>* out_ranges, const uint8_t* data, size_t size,
2869196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        uint32_t defaultUVSTableOffset, uint32_t nonDefaultUVSTableOffset,
2879196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const SparseBitSet& baseCoverage) {
2889196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    // Need to merge supported ranges from default UVS Table and non-default UVS Table.
2899196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    // First, collect all supported code points from non default UVS table.
2909196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    std::vector<uint32_t> rangesFromNonDefaultUVSTable;
2919196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    if (nonDefaultUVSTableOffset != 0) {
2929196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        constexpr size_t kHeaderSize = 4;
2939196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        constexpr size_t kUVSMappingRecordSize = 5;
2949196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
2959196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const uint8_t* nonDefaultUVSTable = data + nonDefaultUVSTableOffset;
2969196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        // This subtraction doesn't underflow since the caller already checked
2979196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        // size > nonDefaultUVSTableOffset.
2989196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const size_t nonDefaultUVSTableRemaining = size - nonDefaultUVSTableOffset;
2999196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        if (nonDefaultUVSTableRemaining < kHeaderSize) {
3009196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            return false;
3019196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        }
3029196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const uint32_t numRecords = readU32(nonDefaultUVSTable, 0);
3039196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        if (numRecords * kUVSMappingRecordSize + kHeaderSize > nonDefaultUVSTableRemaining) {
3049196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            return false;
3059196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        }
3069196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        for (uint32_t i = 0; i < numRecords; ++i) {
3079196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            const size_t recordOffset = kHeaderSize + kUVSMappingRecordSize * i;
3089196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            const uint32_t codePoint = readU24(nonDefaultUVSTable, recordOffset);
3099196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            addRange(rangesFromNonDefaultUVSTable, codePoint, codePoint + 1);
3109196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        }
3119196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    }
3129196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
3139196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    // Then, construct range from default UVS Table with merging code points from non default UVS
3149196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    // table.
3159196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    std::vector<uint32_t> rangesFromDefaultUVSTable;
3169196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    if (defaultUVSTableOffset != 0) {
3179196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        constexpr size_t kHeaderSize = 4;
3189196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        constexpr size_t kUnicodeRangeRecordSize = 4;
3199196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
3209196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const uint8_t* defaultUVSTable = data + defaultUVSTableOffset;
3219196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        // This subtraction doesn't underflow since the caller already checked
3229196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        // size > defaultUVSTableOffset.
3239196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const size_t defaultUVSTableRemaining = size - defaultUVSTableOffset;
3249196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
3259196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        if (defaultUVSTableRemaining < kHeaderSize) {
3269196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            return false;
3279196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        }
3289196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const uint32_t numRecords = readU32(defaultUVSTable, 0);
3299196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        if (numRecords * kUnicodeRangeRecordSize + kHeaderSize > defaultUVSTableRemaining) {
3309196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            return false;
3319196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        }
3329196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
3339196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        for (uint32_t i = 0; i < numRecords; ++i) {
3349196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            const size_t recordOffset = kHeaderSize + kUnicodeRangeRecordSize * i;
3359196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            const uint32_t startCp = readU24(defaultUVSTable, recordOffset);
3369196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            const uint8_t rangeLength = defaultUVSTable[recordOffset + 3];
3379196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
3389196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            // Then insert range from default UVS Table, but exclude if the base codepoint is not
3399196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            // supported.
3409196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            for (uint32_t cp = startCp; cp <= startCp + rangeLength; ++cp) {
3419196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                // All codepoints in default UVS table should go to the glyphs of the codepoints
3429196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                // without variation selectors. We need to check the default glyph availability and
3439196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                // exclude the codepoint if it is not supported by defualt cmap table.
3449196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                if (baseCoverage.get(cp)) {
3459196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                    addRange(rangesFromDefaultUVSTable, cp, cp + 1 /* exclusive */);
3469196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                }
3479196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            }
3489196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        }
3499196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    }
3509196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    *out_ranges = mergeRanges(rangesFromDefaultUVSTable, rangesFromNonDefaultUVSTable);
3519196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    return true;
3529196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka}
3539196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
3549196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonakastatic void getCoverageFormat14(std::vector<std::unique_ptr<SparseBitSet>>* out,
3559196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const uint8_t* data, size_t size, const SparseBitSet& baseCoverage) {
3569196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    constexpr size_t kHeaderSize = 10;
3579196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    constexpr size_t kRecordSize = 11;
3589196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    constexpr size_t kLengthOffset = 2;
3599196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    constexpr size_t kNumRecordOffset = 6;
3609196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
3619196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    out->clear();
3629196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    if (size < kHeaderSize) {
3639196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        return;
3649196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    }
3659196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
3669196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    const uint32_t length = readU32(data, kLengthOffset);
3679196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    if (size < length) {
3689196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        return;
3699196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    }
3709196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
3719196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    uint32_t numRecords = readU32(data, kNumRecordOffset);
3729196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    if (numRecords == 0 || kHeaderSize + kRecordSize * numRecords > length) {
3739196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        return;
3749196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    }
3759196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
3769196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    for (uint32_t i = 0; i < numRecords; ++i) {
3779196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        // Insert from the largest code points since it determines the size of the output vector.
3789196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const uint32_t recordHeadOffset = kHeaderSize + kRecordSize * (numRecords - i - 1);
3799196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const uint32_t vsCodePoint = readU24(data, recordHeadOffset);
3809196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const uint32_t defaultUVSOffset = readU32(data, recordHeadOffset + 3);
3819196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const uint32_t nonDefaultUVSOffset = readU32(data, recordHeadOffset + 7);
3829196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        if (defaultUVSOffset > length || nonDefaultUVSOffset > length) {
3839196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            continue;
3849196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        }
3859196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
3869196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const uint16_t vsIndex = getVsIndex(vsCodePoint);
3879196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        if (vsIndex == INVALID_VS_INDEX) {
3889196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            continue;
3899196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        }
3909196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        std::vector<uint32_t> ranges;
3919196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        if (!getVSCoverage(&ranges, data, length, defaultUVSOffset, nonDefaultUVSOffset,
3929196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                baseCoverage)) {
3939196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            continue;
3949196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        }
3959196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        if (out->size() < vsIndex + 1) {
3969196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            out->resize(vsIndex + 1);
3979196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        }
3989196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        (*out)[vsIndex].reset(new SparseBitSet(ranges.data(), ranges.size() >> 1));
3999196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    }
4009196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
4019196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    out->shrink_to_fit();
4029196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka}
4039196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
404db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo NonakaSparseBitSet CmapCoverage::getCoverage(const uint8_t* cmap_data, size_t cmap_size,
4059196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        std::vector<std::unique_ptr<SparseBitSet>>* out) {
406db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    constexpr size_t kHeaderSize = 4;
407db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    constexpr size_t kNumTablesOffset = 2;
408db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    constexpr size_t kTableSize = 8;
409db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    constexpr size_t kPlatformIdOffset = 0;
410db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    constexpr size_t kEncodingIdOffset = 2;
411db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    constexpr size_t kOffsetOffset = 4;
412db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    constexpr size_t kFormatOffset = 0;
4139196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    constexpr uint32_t kNoTable = UINT32_MAX;
414db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
4159cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    if (kHeaderSize > cmap_size) {
416db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return SparseBitSet();
4179cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
418ca8ac8acdad662230ae37998c6c4091bb39402b6Raph Levien    uint32_t numTables = readU16(cmap_data, kNumTablesOffset);
4199cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    if (kHeaderSize + numTables * kTableSize > cmap_size) {
420db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        return SparseBitSet();
4219cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
422db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
4239196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    uint32_t bestTableOffset = kNoTable;
424db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    uint16_t bestTableFormat = 0;
425db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    uint8_t bestTablePriority = kLowestPriority;
4269196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    uint32_t vsTableOffset = kNoTable;
427db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka    for (uint32_t i = 0; i < numTables; ++i) {
428db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        const uint32_t tableHeadOffset = kHeaderSize + i * kTableSize;
429db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        const uint16_t platformId = readU16(cmap_data, tableHeadOffset + kPlatformIdOffset);
430db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        const uint16_t encodingId = readU16(cmap_data, tableHeadOffset + kEncodingIdOffset);
431db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        const uint32_t offset = readU32(cmap_data, tableHeadOffset + kOffsetOffset);
432db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
433db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        if (offset > cmap_size - 2) {
434db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            continue;  // Invalid table: not enough space to read.
435db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        }
436db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        const uint16_t format = readU16(cmap_data, offset + kFormatOffset);
437db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
438db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        if (platformId == 0 /* Unicode */ && encodingId == 5 /* Variation Sequences */) {
4399196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            if (vsTableOffset == kNoTable && format == 14) {
4409196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka                vsTableOffset = offset;
441db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            } else {
442db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                // Ignore the (0, 5) table if we have already seen another valid one or it's in a
443db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                // format we don't understand.
444db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            }
445db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        } else {
446db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            uint32_t length;
447db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            uint32_t language;
448db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
449db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            if (format == 4) {
450db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                constexpr size_t lengthOffset = 2;
451db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                constexpr size_t languageOffset = 4;
452db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                constexpr size_t minTableSize = languageOffset + 2;
453db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                if (offset > cmap_size - minTableSize) {
454db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                    continue;  // Invalid table: not enough space to read.
455db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                }
456db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                length = readU16(cmap_data, offset + lengthOffset);
457db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                language = readU16(cmap_data, offset + languageOffset);
458db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            } else if (format == 12) {
459db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                constexpr size_t lengthOffset = 4;
460db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                constexpr size_t languageOffset = 8;
461db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                constexpr size_t minTableSize = languageOffset + 4;
462db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                if (offset > cmap_size - minTableSize) {
463db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                    continue;  // Invalid table: not enough space to read.
464db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                }
465db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                length = readU32(cmap_data, offset + lengthOffset);
466db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                language = readU32(cmap_data, offset + languageOffset);
467db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            } else {
468db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                continue;
469db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            }
470db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
471db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            if (length > cmap_size - offset) {
472db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                continue;  // Invalid table: table length is larger than whole cmap data size.
473db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            }
474db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            if (language != 0) {
475db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                // Unsupported or invalid table: this is either a subtable for the Macintosh
476db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                // platform (which we don't support), or an invalid subtable since language field
477db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                // should be zero for non-Macintosh subtables.
478db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                continue;
479db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            }
480db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            const uint8_t priority = getTablePriority(platformId, encodingId);
481db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            if (priority < bestTablePriority) {
482db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                bestTableOffset = offset;
483db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                bestTablePriority = priority;
484db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka                bestTableFormat = format;
4856b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka            }
4869cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        }
4879196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        if (vsTableOffset != kNoTable && bestTablePriority == 0 /* highest priority */) {
488db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            // Already found the highest priority table and variation sequences table. No need to
489db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            // look at remaining tables.
490db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka            break;
491db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka        }
4929cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
4939196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
4949196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    SparseBitSet coverage;
4959196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
4969196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    if (bestTableOffset != kNoTable) {
4979196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const uint8_t* tableData = cmap_data + bestTableOffset;
4989196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const size_t tableSize = cmap_size - bestTableOffset;
4999196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        bool success;
5009196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        vector<uint32_t> coverageVec;
5019196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        if (bestTableFormat == 4) {
5029196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            success = getCoverageFormat4(coverageVec, tableData, tableSize);
5039196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        } else {
5049196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            success = getCoverageFormat12(coverageVec, tableData, tableSize);
5059196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        }
5069196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka
5079196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        if (success) {
5089196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka            coverage = SparseBitSet(&coverageVec.front(), coverageVec.size() >> 1);
5099196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        }
5109cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
511db1b6cb7765091453d9b4dc7f6c2fb4d7123ab11Seigo Nonaka
5129196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    if (vsTableOffset != kNoTable) {
5139196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const uint8_t* tableData = cmap_data + vsTableOffset;
5149196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        const size_t tableSize = cmap_size - vsTableOffset;
5159196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka        getCoverageFormat14(out, tableData, tableSize, coverage);
5169196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    }
5179196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    return coverage;
5189cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
5199cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
52014e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonaka}  // namespace minikin
521