1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef MINIKIN_HASHER_H 18 #define MINIKIN_HASHER_H 19 20 #include <cstdint> 21 #include <string> 22 23 #include "minikin/FontFeature.h" 24 #include "minikin/FontVariation.h" 25 #include "minikin/Macros.h" 26 #include "minikin/SortedPackedVector.h" 27 28 namespace minikin { 29 30 // Provides a Jenkins hash implementation. 31 class Hasher { 32 public: Hasher()33 Hasher() : mHash(0u) {} 34 update(uint32_t data)35 IGNORE_INTEGER_OVERFLOW inline Hasher& update(uint32_t data) { 36 mHash += data; 37 mHash += (mHash << 10); 38 mHash ^= (mHash >> 6); 39 return *this; 40 } 41 update(int32_t data)42 inline Hasher& update(int32_t data) { 43 update(static_cast<uint32_t>(data)); 44 return *this; 45 } 46 update(uint64_t data)47 inline Hasher& update(uint64_t data) { 48 update(static_cast<uint32_t>(data)); 49 update(static_cast<uint32_t>(data >> 32)); 50 return *this; 51 } 52 update(float data)53 inline Hasher& update(float data) { 54 union { 55 float f; 56 uint32_t i; 57 } bits; 58 bits.f = data; 59 return update(bits.i); 60 } 61 update(const std::vector<FontFeature> & features)62 inline Hasher& update(const std::vector<FontFeature>& features) { 63 uint32_t size = features.size(); 64 update(size); 65 for (const FontFeature& feature : features) { 66 update(feature); 67 } 68 return *this; 69 } 70 update(const FontFeature & feature)71 inline Hasher& update(const FontFeature& feature) { 72 update(feature.tag); 73 update(feature.value); 74 return *this; 75 } 76 update(const VariationSettings & vars)77 inline Hasher& update(const VariationSettings& vars) { 78 update(vars.size()); 79 for (const FontVariation& var : vars) { 80 update(var.axisTag); 81 update(var.value); 82 } 83 return *this; 84 } 85 86 template <typename V> updatePackedVector(const V & vec)87 inline Hasher& updatePackedVector(const V& vec) { 88 using T = typename V::value_type; 89 for (const T& p : vec) { 90 update(p); 91 } 92 return *this; 93 } 94 updateShorts(const uint16_t * data,uint32_t length)95 inline Hasher& updateShorts(const uint16_t* data, uint32_t length) { 96 update(length); 97 uint32_t i; 98 for (i = 0; i < (length & -2); i += 2) { 99 update((uint32_t)data[i] | ((uint32_t)data[i + 1] << 16)); 100 } 101 if (length & 1) { 102 update((uint32_t)data[i]); 103 } 104 return *this; 105 } 106 updateString(const std::string & str)107 inline Hasher& updateString(const std::string& str) { 108 uint32_t size = str.size(); 109 update(size); 110 uint32_t i; 111 for (i = 0; i < (size & -4); i += 4) { 112 update((uint32_t)str[i] | ((uint32_t)str[i + 1] << 8) | ((uint32_t)str[i + 2] << 16) | 113 ((uint32_t)str[i + 3] << 24)); 114 } 115 if (size & 3) { 116 uint32_t data = str[i]; 117 data |= ((size & 3) > 1) ? ((uint32_t)str[i + 1] << 8) : 0; 118 data |= ((size & 3) > 2) ? ((uint32_t)str[i + 2] << 16) : 0; 119 update(data); 120 } 121 return *this; 122 } 123 update(const FontVariation & var)124 inline Hasher& update(const FontVariation& var) { 125 update(static_cast<uint32_t>(var.axisTag)); 126 update(static_cast<float>(var.value)); 127 return *this; 128 } 129 130 template <typename T, size_t ARRAYSIZE> update(const SortedPackedVector<T,ARRAYSIZE> & vec)131 inline Hasher& update(const SortedPackedVector<T, ARRAYSIZE>& vec) { 132 uint32_t size = vec.size(); 133 update(size); 134 for (uint32_t i = 0; i < size; ++i) { 135 update(vec[i]); 136 } 137 return *this; 138 } 139 hash()140 IGNORE_INTEGER_OVERFLOW inline uint32_t hash() { 141 uint32_t hash = mHash; 142 hash += (hash << 3); 143 hash ^= (hash >> 11); 144 hash += (hash << 15); 145 return hash; 146 } 147 148 #ifdef __APPLE__ update(uintptr_t data)149 inline Hasher& update(uintptr_t data) { 150 update(static_cast<uint32_t>(data)); 151 if (sizeof(uintptr_t) > sizeof(uint32_t)) { 152 update(static_cast<uint32_t>(data >> 32)); 153 } 154 return *this; 155 } 156 #endif 157 158 private: 159 uint32_t mHash; 160 }; 161 162 } // namespace minikin 163 164 #endif // MINIKIN_HASHER_H 165