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