1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2019 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/private/SkTFitsIn.h" 9cb93a386Sopenharmony_ci#include "src/utils/SkCharToGlyphCache.h" 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ciSkCharToGlyphCache::SkCharToGlyphCache() { 12cb93a386Sopenharmony_ci this->reset(); 13cb93a386Sopenharmony_ci} 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ciSkCharToGlyphCache::~SkCharToGlyphCache() {} 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_civoid SkCharToGlyphCache::reset() { 18cb93a386Sopenharmony_ci fK32.reset(); 19cb93a386Sopenharmony_ci fV16.reset(); 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ci // Add sentinels so we can always rely on these to stop linear searches (in either direction) 22cb93a386Sopenharmony_ci // Neither is a legal unichar, so we don't care what glyphID we use. 23cb93a386Sopenharmony_ci // 24cb93a386Sopenharmony_ci *fK32.append() = 0x80000000; *fV16.append() = 0; 25cb93a386Sopenharmony_ci *fK32.append() = 0x7FFFFFFF; *fV16.append() = 0; 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ci fDenom = 0; 28cb93a386Sopenharmony_ci} 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ci// Determined experimentally. For N much larger, the slope technique is faster. 31cb93a386Sopenharmony_ci// For N much smaller, a simple search is faster. 32cb93a386Sopenharmony_ci// 33cb93a386Sopenharmony_ciconstexpr int kSmallCountLimit = 16; 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ci// To use slope technique we need at least 2 real entries (+2 sentinels) hence the min of 4 36cb93a386Sopenharmony_ci// 37cb93a386Sopenharmony_ciconstexpr int kMinCountForSlope = 4; 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_cistatic int find_simple(const SkUnichar base[], int count, SkUnichar value) { 40cb93a386Sopenharmony_ci int index; 41cb93a386Sopenharmony_ci for (index = 0;; ++index) { 42cb93a386Sopenharmony_ci if (value <= base[index]) { 43cb93a386Sopenharmony_ci if (value < base[index]) { 44cb93a386Sopenharmony_ci index = ~index; // not found 45cb93a386Sopenharmony_ci } 46cb93a386Sopenharmony_ci break; 47cb93a386Sopenharmony_ci } 48cb93a386Sopenharmony_ci } 49cb93a386Sopenharmony_ci return index; 50cb93a386Sopenharmony_ci} 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_cistatic int find_with_slope(const SkUnichar base[], int count, SkUnichar value, double denom) { 53cb93a386Sopenharmony_ci SkASSERT(count >= kMinCountForSlope); 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ci int index; 56cb93a386Sopenharmony_ci if (value <= base[1]) { 57cb93a386Sopenharmony_ci index = 1; 58cb93a386Sopenharmony_ci if (value < base[index]) { 59cb93a386Sopenharmony_ci index = ~index; 60cb93a386Sopenharmony_ci } 61cb93a386Sopenharmony_ci } else if (value >= base[count - 2]) { 62cb93a386Sopenharmony_ci index = count - 2; 63cb93a386Sopenharmony_ci if (value > base[index]) { 64cb93a386Sopenharmony_ci index = ~(index + 1); 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci } else { 67cb93a386Sopenharmony_ci // make our guess based on the "slope" of the current values 68cb93a386Sopenharmony_ci// index = 1 + (int64_t)(count - 2) * (value - base[1]) / (base[count - 2] - base[1]); 69cb93a386Sopenharmony_ci index = 1 + (int)(denom * (count - 2) * (value - base[1])); 70cb93a386Sopenharmony_ci SkASSERT(index >= 1 && index <= count - 2); 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ci if (value >= base[index]) { 73cb93a386Sopenharmony_ci for (;; ++index) { 74cb93a386Sopenharmony_ci if (value <= base[index]) { 75cb93a386Sopenharmony_ci if (value < base[index]) { 76cb93a386Sopenharmony_ci index = ~index; // not found 77cb93a386Sopenharmony_ci } 78cb93a386Sopenharmony_ci break; 79cb93a386Sopenharmony_ci } 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci } else { 82cb93a386Sopenharmony_ci for (--index;; --index) { 83cb93a386Sopenharmony_ci SkASSERT(index >= 0); 84cb93a386Sopenharmony_ci if (value >= base[index]) { 85cb93a386Sopenharmony_ci if (value > base[index]) { 86cb93a386Sopenharmony_ci index = ~(index + 1); 87cb93a386Sopenharmony_ci } 88cb93a386Sopenharmony_ci break; 89cb93a386Sopenharmony_ci } 90cb93a386Sopenharmony_ci } 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci return index; 94cb93a386Sopenharmony_ci} 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ciint SkCharToGlyphCache::findGlyphIndex(SkUnichar unichar) const { 97cb93a386Sopenharmony_ci const int count = fK32.count(); 98cb93a386Sopenharmony_ci int index; 99cb93a386Sopenharmony_ci if (count <= kSmallCountLimit) { 100cb93a386Sopenharmony_ci index = find_simple(fK32.begin(), count, unichar); 101cb93a386Sopenharmony_ci } else { 102cb93a386Sopenharmony_ci index = find_with_slope(fK32.begin(), count, unichar, fDenom); 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci if (index >= 0) { 105cb93a386Sopenharmony_ci return fV16[index]; 106cb93a386Sopenharmony_ci } 107cb93a386Sopenharmony_ci return index; 108cb93a386Sopenharmony_ci} 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_civoid SkCharToGlyphCache::insertCharAndGlyph(int index, SkUnichar unichar, SkGlyphID glyph) { 111cb93a386Sopenharmony_ci SkASSERT(fK32.size() == fV16.size()); 112cb93a386Sopenharmony_ci SkASSERT((unsigned)index < fK32.size()); 113cb93a386Sopenharmony_ci SkASSERT(unichar < fK32[index]); 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ci *fK32.insert(index) = unichar; 116cb93a386Sopenharmony_ci *fV16.insert(index) = glyph; 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ci // if we've changed the first [1] or last [count-2] entry, recompute our slope 119cb93a386Sopenharmony_ci const int count = fK32.count(); 120cb93a386Sopenharmony_ci if (count >= kMinCountForSlope && (index == 1 || index == count - 2)) { 121cb93a386Sopenharmony_ci SkASSERT(index >= 1 && index <= count - 2); 122cb93a386Sopenharmony_ci fDenom = 1.0 / ((double)fK32[count - 2] - fK32[1]); 123cb93a386Sopenharmony_ci } 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ci#ifdef SK_DEBUG 126cb93a386Sopenharmony_ci for (int i = 1; i < fK32.count(); ++i) { 127cb93a386Sopenharmony_ci SkASSERT(fK32[i-1] < fK32[i]); 128cb93a386Sopenharmony_ci } 129cb93a386Sopenharmony_ci#endif 130cb93a386Sopenharmony_ci} 131