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